I would just recommend trying to model the entire river bed + hills / mountains into an actual model and use that instead of sprite stacks, as that could get costly like you mentioned. I would recommend looking into TerrainOps by DragoniteSpam
Gizmo199
Creator of
Recent community posts
It uses a rotational sample blur instead of a box/gaussian blur. This was mostly done for performance reasons as sample blurring is more efficient and also fit the 'aesthetic' of the project. You can replace the shader code for the `blur()` function in the `shd_horrifi` fragment shader to another method of blurring if you would like. :) If you are looking for a more general purpose post processing shader, however, I would recommend FoxyOfJungle's Post Processing FX instead, as it will offer what horrifi does and MUCH MUCH more with better results. :)
I Hope this helps!
it could be that this code is running after all of your GUI elements (e.g. the object drawing the application surface runs its GUI draw event after the other GUI elements). You can try to place this instead in the "GUI Begin" event or setting this object to a higher depth / lower layer I believe.
Hope this helps. :)
You can just copy over the shader yes. It should work fine with 1. You will just need to set up the uniforms yourself. :) You can also check out this Vignette shader on shader toy and copy it over. You just need to make a few changes. Vignette is pretty easy to make work.
So essentially you need to do some matrix multiplication of the screen coordinates to convert them to world coordinates and visa versa. The camera in fauxton uses an actual 3d camera so you can follow along this tutorial to get the right coordinates:
I cannot recommend dragonitespams gamemaker 3d tutorials enough! If you are ever interested in learning full 3d in GM, he has a huge catalog of various tutorials for creating 3d environments and such in Game Maker!haha, the score is kind of cheating really. I just add and subtract scores based on which paintball splats and from which player it came from. I wanted to add in a grid checking system for % of area covered but didn't have time. It (sort of )effectively works the same way since as long as a player is shooting paintballs they are technically covering area, but its not super in-depth when it comes to the score calculations. haha.
It doesn't have it built in, but you can add it using the "gpu_set_cullmode()" function that Game Maker has. Please keep in mind, however, that this system is for sprite stacking, and doesn't have .obj model support built in, so back-face culling won't be incredibly useful for sprite stacks since they are essentially a stack of 2d planes. This is mostly a quick and dirty 3D solution for beginners, but it should really only be a stepping stone to learning full 3D IMO. :)
If you want to learn more about 3D in Game Maker I cannot recommend Dragonitespam's 3D tutorials enough! They are really well done, and pretty much how I learned to even make this system! haha.
Best of luck! :)
hey! So the horrifi_fragment and horrifi_vertex are the code you would put into a new shader. Then you would just put the lib_horrifi code into a blank script and use the horrify_* functions. the unknown object should be the global.__horriFi variable. I would recommend dragging and dropping the .yymps file into your game and adding the lib_horrifi script and the shd_horrifi shader.
So I never realized I don't have the alpha being transmitted to the shader. I think I am doing the alpha on creation only, but it needs to be done in the shader instead. So if you go into Scripts > lib_RenderPipelineScripts
and go down to pipeline_render()
and where it says m = RENDER_QUEUE[| i];
you can add this:
shader_set_uniform_f(shader_get_uniform(shader_current(), "alpha"), m.alpha);
And then I would change the shd_default
fragment shader to this:
varying vec2 v_vTexcoord; varying vec4 v_vColour; varying vec3 v_vNormal; varying vec3 v_vWorldPosition; uniform vec3 ambient_color; uniform vec3 sun_color; uniform vec3 sun_pos; uniform float sun_intensity; uniform float lightTotal; uniform vec3 lightPos[64]; uniform vec3 lightColor[64]; uniform float lightRange[64]; uniform float lightIsCone[64]; uniform vec3 lightDirection[64]; uniform float lightCutoffAngle[64]; uniform float alpha; // Pointlights float evaluate_point_light(vec3 world_position, vec3 world_normal, vec3 light_position, float light_radius) { // Light position vec3 lightIncome = world_position - light_position; // Light magnitude float lightDist = length(lightIncome); // Send light back lightIncome = normalize(-lightIncome); float lDiff = max(dot(world_normal, lightIncome), 0.); // Attenuation float lightAtt = clamp( 1. - lightDist*lightDist/( light_radius*light_radius ), 0., 1. );
lightAtt *= lightAtt; // Return attenuation mulitplied by the light sent back return lightAtt * lDiff; } // Spotlights float evaluate_cone_light(vec3 world_position, vec3 world_normal, vec3 light_direction, float cutoff, vec3 light_position, float light_radius) { // Light position vec3 lightIncome = world_position - light_position; // Light magnitude float lightDist = length(lightIncome); // Send light back lightIncome = normalize(-lightIncome); float lDiff = max(dot(world_normal, lightIncome), 0.); // Attenuation float cAng = max(dot(lightIncome, -normalize(light_direction)), 0.); float lightAtt = 0.; // Cut off attenuation for spot lights if ( cAng > cutoff ) { lightAtt = max(( light_radius - lightDist ) / light_radius, 0.); } // Return attenuation by returning light return lightAtt * lDiff; } void main() { vec4 col = texture2D( gm_BaseTexture, v_vTexcoord ) * v_vColour; // Alpha if ( col.a < 0.05 ) { discard; } // Diffuse and ambient float nDot = max(dot(v_vNormal, normalize(sun_pos)), 0.); col.rgb *= ( ambient_color ) + ( sun_color * sun_intensity ) * nDot; // Spot & Point lights if ( lightTotal > 0. ){ float eval = 0.; for ( int i=0; i<64; i++ ) { if ( float(i) > lightTotal ) { break; } if ( lightIsCone[i] == 1. ) { eval = evaluate_cone_light(v_vWorldPosition, v_vNormal, lightDirection[i], lightCutoffAngle[i], lightPos[i], lightRange[i]); } else { eval = evaluate_point_light(v_vWorldPosition, v_vNormal, lightPos[i], lightRange[i]); } col += eval * vec4( min( lightColor[i], 1. ), 1. ); } } col.a = alpha; // Final color gl_FragColor = min( col, vec4(vec3(1), alpha) ); }
absolutely! It's just a shader so you can treat it as you would any other shader. My example just shows it used on the application surfaces since it was designed with 'post processing' in mind, but it can be used for anything you want! You just might need to go into the scripts and copy some things for use outside of the functions I have provided. :)