Giter Site home page Giter Site logo

fnf-modshaders's Introduction

Shader stealing porting 101

1. Adding this to FNF:

(THIS MIGHT BREAK ANY SHADERS YOU USED BEFORE)

  • Copy the source and assets folder to your fnf source folder.

  • Add this in your Paths.hx

inline static public function shaderFragment(key:String, ?library:String)
{
	return getPath('shaders/$key.frag', TEXT, library);
}
  • Add these to your PlayState.hx

    • At the start:
import DynamicShaderHandler;
  • In the variables:
public static var animatedShaders:Map<String, DynamicShaderHandler> = new Map<String, DynamicShaderHandler>();
  • In update function:
for (shader in animatedShaders)
{
	shader.update(elapsed);
}
  • In update function (if Lua is used):
#if #FEATURE_LUAMODCHART
for (key => value in luaModchart.luaShaders)
{
	value.update(elapsed);
}
#end
  • Add these to your ModchartState.hx for Lua support (KE / KE forks only)

    • In the variables:
public var luaShaders:Map<String, DynamicShaderHandler> = new Map<String, DynamicShaderHandler>();
public var camTarget:FlxCamera;
  • As Lua callbacks:
import openfl.filters.BitmapFilter;

Lua_helper.add_callback(lua, "createShaders", function(shaderName, ?optimize:Bool = false)
{
	var shader = new DynamicShaderHandler(shaderName, optimize);

	return shaderName;
});

Lua_helper.add_callback(lua, "modifyShaderProperty", function(shaderName, propertyName, value)
{
	var handler = luaShaders[shaderName];
	handler.modifyShaderProperty(propertyName, value);
});

// shader set

Lua_helper.add_callback(lua, "setShadersToCamera", function(shaderName:Array<String>, cameraName)
{
	switch (cameraName)
	{
		case 'hud':
			camTarget = PlayState.instance.camHUD;
		case 'notes':
			camTarget = PlayState.instance.camNotes;
		case 'sustains':
			camTarget = PlayState.instance.camSustains;
		case 'game':
			camTarget = FlxG.camera;
	}

	var shaderArray = new Array<BitmapFilter>();

	for (i in shaderName)
	{
		shaderArray.push(new ShaderFilter(luaShaders[i].shader));
	}

	camTarget.setFilters(shaderArray);
});

// shader clear

Lua_helper.add_callback(lua, "clearShadersFromCamera", function(cameraName)
{
	switch (cameraName)
	{
		case 'hud':
			camTarget = PlayState.instance.camHUD;
		case 'notes':
			camTarget = PlayState.instance.camNotes;
		case 'sustains':
			camTarget = PlayState.instance.camSustains;
		case 'game':
			camTarget = FlxG.camera;
	}
	camTarget.setFilters([]);
});

2. Porting Shaders from shadertoy:

(PLEASE MAKE SURE TO READ THE LICENSE OF THE SHADER YOU ARE PORTING)

  • First of all, you need to know that shadertoy automatically uses the inputs below:
uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform float     iTime;                 // shader playback time (in seconds)
uniform float     iTimeDelta;            // render time (in seconds)
uniform int       iFrame;                // shader playback frame
uniform float     iChannelTime[4];       // channel playback time (in seconds)
uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3;          // input channel. XX = 2D/Cube
uniform vec4      iDate;                 // (year, month, day, time in seconds)
uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

Currently, my implementation only supports the following inputs: (iResolution, iTime, iChannel0).

Support for iMouse input is planned for the future.

The shader code is the following:

const float RADIUS	= 100.0;
const float BLUR	= 200.0;
const float SPEED   = 2.0;
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec4 pic = texture(iChannel0, vec2(uv.x, uv.y));
    
    vec2 center = iResolution.xy / 2.0;
    float d = distance(fragCoord.xy, center);
    float intensity = max((d - RADIUS) / (2.0 + BLUR * (1.0 + sin(iTime*SPEED))), 0.0);
    
    fragColor = vec4(intensity + pic.r, intensity + pic.g, intensity + pic.b, 1.0);
}

We need to modify some stuff,

  • main function header void mainImage( out vec4 fragColor, in vec2 fragCoord ) should be changed to void main() and add this new line at the start of function: vec2 fragCoord = openfl_TextureCoordv * iResolution;

  • The shader outputs to fragColor, this should be changed to gl_FragColor

  • at the very start of the shader add those two uniforms: uniform vec2 iResolution; uniform float iTime;

  • if your shader makes use of iChannel0 sampler, change that to bitmap, other channels are not supported (unless replacing them all with bitmap still serves your purpose, use common sense)

  • if your shader outputs alpha pixels and they're black (Black instead of transparent), Make sure to use\change texture function to texture2D instead of texture

  • The final result should be like this:

    uniform vec2 iResolution;
    uniform float iTime;

    const float RADIUS	= 200.0;
    const float BLUR	= 500.0;
    const float SPEED   = 2.0;

    void main()
    {
        vec2 fragCoord = openfl_TextureCoordv * iResolution;

        vec2 uv = fragCoord.xy / iResolution.xy;
        vec4 pic = texture2D(bitmap, vec2(uv.x, uv.y));
        
        vec2 center = iResolution.xy / 2.0;
        float d = distance(fragCoord.xy, center);
        float intensity = max((d - RADIUS) / (2.0 + BLUR * (1.0 + sin(iTime*SPEED))), 0.0);

        gl_FragColor = vec4(intensity + pic.r, intensity + pic.g, intensity + pic.b, 0.2);
    }

3. Usage through Haxe:

  • Shaders should be placed in /shaders folder, with .frag extension, See shaders folder for more examples.
  • Params are the file name and optimize bool, this might help with heavy shaders but only makes a difference on decent Intel CPUs (ones with SSE Instructions support).
new DynamicShaderHandler("Example");
FlxG.camera.setFilters([new ShaderFilter(animatedShaders["Example"].shader)]);

or

var spr:FlxSprite = new ShaderSprite("Example");

4. Usage through Lua:

  • You can initialize shaders through Lua using this function (parameters are shader name and optimize (optional))
createShaders("Example",true)
  • You can load shaders onto cameras using this function (parameters are array of shader names and camera)
setShadersToCamera({"Example"},camera)
  • You can clear shader filters using this function (parameters are camera name):
clearShadersFromCamera(camera)
  • And you can modify shader uniforms with this method (parameters are shader name, property and value):
modifyShaderProperty("Example","Property",Value)
  • Valid cameras are "game", "hud", "notes" and "sustains".

Credits:

  • SqirraRNG: Runtime shaders workaround.

  • Kemo (me): Handler, Improvements, Guide.

  • Fireable: Lua implementation

    • If you are going to port this to any engine, please make sure to leave a noticable credit and respect the effort, this was planned to be nexus engine exclusive but there ya :).

    • If you run into any issues (that aren't common sense), feel free to DM me on discord kemo#1337.

fnf-modshaders's People

Contributors

itzfireable avatar kem0x avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.