Lego style split screen camera in godot - godot

I want to have lego style splitscreen camera with seamless transitions.
Anyone has any experience creating something like this? I thought of creating one normal camera and then another camera for second player that by default wouldn't be visible. Then, when i would want to show it, i would draw a triangle to split the screen and set it texture as camera #2 view.
I found this Unity implementation but i couldn't implement it in Godot. I've managed to create second viewport with it's own camera, but for some reason the view of the second camera is not showing anything. I'm thinking that the problem is that the world of the second viewport is different than the main viewport.
Source code can be found here.

I just setup a toy project to test this out and it turned out to be simpler than expected.
Here is an overview of the process and then code examples will follow.
Add one main camera
And a secondary camera with tree: Control > Viewport > Camera
Draw the shape of the split screen with Control using the draw_* api
Add a shader to Control that takes a texture and draws it at SCREEN_UV
Get the viewport texture from Viewport
Pass the viewport texture to the Control shader every frame.
Animate the split by animating and redrawing the Control shape.
I'm not sure how to do the border.
To make the split join you'll probably have to shift the Control shape by the thickness of border and then shrink that border as the cameras go towards each other. Use that distance between the players to calculate the border width.
The split border is also at an angle between the two players so when animating the shape you'll want to use that angle. This will make the joining of the viewport look smoother.
Control code:
extends Control
func _draw():
# in this case animate tl and bml to get the
# rotating split like effect in the lego game
var tl = Vector2()
var tr = rect_size
tr.y = 0
var br = rect_size
var bml = rect_size
bml.x /= 2.0
draw_polygon([tl, tr, br, bml, tl], [Color(), Color(), Color(), Color(), Color()], [])
func _process(d):
material.set_shader_param('viewport', $Viewport.get_texture())
Shader Code:
shader_type canvas_item;
uniform sampler2D viewport;
void fragment(){
COLOR=texture(viewport, SCREEN_UV);
}
I hope this helps get you started!

It is a complex effect with many parts so be warned.
I found that the easiest way is to create a separate scene with your viewports and cameras which will be your main scene and then add your game scene under it like this:
Spatial
Viewport1
Camera1
Viewport2
Camera2
GameScene
You should then be able to make a ColorRect with a shader material and send in the textures from each viewport:
shader_type canvas_item;
render_mode unshaded, cull_disabled;
uniform sampler2D viewport1;
uniform sampler2D viewport2;
void fragment() {
vec3 view1 = texture(viewport1, UV).rgb;
vec3 view2 = texture(viewport2, UV).rgb;
vec3 col = vec3(0);
// mix them in a satisfying way depending on distance and angle between cameras
// float mixVal = <your formula here>
// col = mix(view1, view2, mixVal)
COLOR = vec4(col, 0.0); // this may not work in Godot shaders
}
This is a great guide to get you started:
https://docs.godotengine.org/en/3.1/tutorials/viewports/using_viewport_as_texture.html

Related

threejs - creating "cel-shading" for objects that are close by

So I'm trying to "outline" 3D objects. Standard problem, for which the answer is meant to be that you copy the mesh, color it the outline color, scale it up, and then set it to only render faces that are "pointed in the wrong direction" - for us that means setting side:THREE.BackSide in the material. Eg here https://stemkoski.github.io/Three.js/Outline.html
But see what happens for me
Here's what I'd like to make
I have a bunch of objects that are close together - they get "inside" one another's outline.
Any advice on what I should do? What I want to be seeing is everywhere on the rendered frame that these shapes touch the background or each other, there you have outline.
What do you want to happen? Is that one mesh in your example or is it a bunch of intersecting meshes. If it's a bunch of intersecting meshes do you want them to have one outline? What about other meshes? My point is you need some way to define which "groups" of meshes get a single outline if you're using multiple meshes.
For multiple meshes and one outline a common solution is to draw all the meshes in a single group to a render target to generate a silhouette, then post process the silhouette to expand it. Finally apply the silhouette to the scene. I don't know of a three.js example but the concept is explained here and there's also many references here
Another solution that might work, should be possible to move the outline shell back in Z so doesn't intersect. Either all the way back (Z = 1 in clip space) or back some settable amount. Drawing with groups so that a collection of objects in front has an outline that blocks a group behind would be harder.
For example if I take this sample that prisoner849 linked to
And change the vertexShaderChunk in OutlineEffect.js to this
var vertexShaderChunk = `
#include <fog_pars_vertex>
uniform float outlineThickness;
vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {
float thickness = outlineThickness;
const float ratio = 1.0; // TODO: support outline thickness ratio for each vertex
vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );
// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
vec4 norm = normalize( pos - pos2 );
// ----[ added ] ----
// compute a clipspace value
vec4 pos3 = pos + norm * thickness * pos.w * ratio;
// do the perspective divide in the shader
pos3.xyz /= pos3.w;
// just return screen 2d values at the back of the clips space
return vec4(pos3.xy, 1, 1);
}
`;
It's easier to see if you remove all references to reflectionCube and set the clear color to white renderer.setClearColor( 0xFFFFFF );
Original:
After:

How to isolate a Phaser shader to a specific object/shape?

I'm using the Phaser framework. Here is the jsfiddle:
http://jsfiddle.net/Dillybob/u3mGL/13/
Here is where the filter is getting populated:
background = game.add.sprite(0, 0);
background.width = 800;
background.height = 600;
filter = game.add.filter('Fire', 800, 600);
filter.alpha = 0.0;
background.filters = [filter];
My line object is assigned to the variable drawnObject
So I assign that object to receive the filter like so:
drawnObject.filters = [filter];
But my line is now a red fiery square instead of being a line with a fiery background, why?
Firstly, be aware that drawnObject is actually a bitmap, which is rectangular shaped. It consists of white pixels, which build your line, and transparent pixels, which are taking the rest of bitmap space.
The filter you use is a pixel shader. Pixel shader describes instructions that GPU invokes for each pixel of a provided bitmap. In case of this shader, it creates fire effect based on some noise functions, but it doesn't take original bitmap into account. The original color of pixels is not preserved, it doesn't add to final effect in any way.
To achieve your expected result, you have to amend fragmentSrc in Fire.js, so that shader uses and mixes/blends original color into final pixel color and/or doesn't change pixel transparency.

androidplot background image shift

I'm trying to separate the background of the graph grid in 3 areas using this code:
int[] data = {0xff000000, 0x80008000, 0xff000000};
bgBitmap = Bitmap.createBitmap(data, 1, 3, Bitmap.Config.ARGB_8888);
RectF rect = plot.getGraphWidget().getGridRect();
BitmapShader myShader = new BitmapShader(
Bitmap.createScaledBitmap(bgBitmap, 1, (int) rect.height(), false),
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
plot.getGraphWidget().getGridBackgroundPaint().setShader(myShader);
So scaling a 3 pixel bitmap to the graph height and repeating it over the whole domain area.
However the resulting graph show that the background seems to be shifted up a bit.
It looks like the shift size is about equal to the domain label height.
How can I fix this?
Hm cannot post picture because of 'reputation' sigh.
Link to the example graph: http://marcel.mesa.nl/androidplot.png
I think you're running into the issue mentioned near the end of this thread. Essentially, the origin of the shader is the top-left corner of the screen, not the top-left corner of component for which the background is being drawn using the shader. The solution is to translate to the top-left point of the graphWidget like this:
RectF rect = plot.getGraphWidget().getGridRect();
Matrix m = new Matrix();
m.setTranslate(rect.left, rect.top);
shader.setLocalMatrix(m); // where shader is your shader instance

How to avoid fade-out on scaled CCSprite without cancelling anti-aliasing?

I have 3 sprites. Left edge, right edge, and repeating center which has 1 pixel width but is scaled up. The problem is that the scaled sprite fades out the farther away it is from the center:
I've tried using CCTexture's setAliasTexParameters but the result doesn't look good:
How do I get the antialiased looks in the first picture but without the fade out problem?
You could try this on the sprite:
// These parameters set the texture properties:
// minifying filter - linear interpolation,
// magnification filter - linear interpolation,
// texture repeat in S direction,
// texture repeat in T direction (*)
ccTexParams params = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
[sprite.texture setTexParams:&params];
// This explicitly sets the contentSize of the sprite to (10, 200),
// but also sets the "window to the texture" to this rectangle:
[sprite setTextureRect:CGRectMake(0, 0, 10, 200)];
You have to tweak these settings, but hope you get it.
You don't have to scale the sprite.
(*) For S and T check this: Difference between U V and S T texture coordinates

HLSL beginner needs some directions

Is there any example out there of a HLSL written .fx file that splats a tiled texture with different tiles?Like this: http://messy-mind.net/blog/wp-content/uploads/2007/10/transitions.jpg you can see theres a different tile type in each square and there's a little blurring between them to make a smoother transition,but right now I just need to find a way to draw the tiles on a texture.I have a 2D array of integers,each integer equals a corresponding tile type(0 = grass,1 = stone,2 = sand).I opened up a few HLSL examples and they were really confusing.Everything is running fine on the C++ side,but HLSL is proving to be difficult.
You can use a technique called 'texture splatting'. It mixes several textures (color maps) using another texture which contains alpha values for each color map. The texture with alpha values is an equivalent of your 2D array. You can create a 3-channel RGB texture and use each channel for a different color map (in your case: R - grass, G - stone, B - sand). Every pixel of this texture tells us how to mix the color maps (for example R=0 means 'no grass', G=1 means 'full stone', B=0.5 means 'sand, half intensity').
Let's say you have four RGB textures: tex1 - grass, tex2 - stone, tex3 - sand, alpha - mixing texture. In your .fx file, you create a simple vertex shader which just calculates the position and passes the texture coordinate on. The whole thing is done in pixel shader, which should look like this:
float tiling_factor = 10; // number of texture's repetitions, you can also
// specify a seperate factor for each texture
float4 PS_TexSplatting(float2 tex_coord : TEXCOORD0)
{
float3 color = float3(0, 0, 0);
float3 mix = tex2D(alpha_sampler, tex_coord).rgb;
color += tex2D(tex1_sampler, tex_coord * tiling_factor).rgb * mix.r;
color += tex2D(tex2_sampler, tex_coord * tiling_factor).rgb * mix.g;
color += tex2D(tex3_sampler, tex_coord * tiling_factor).rgb * mix.b;
return float4(color, 1);
}
If your application supports multi-pass rendering you should use it.
You should use a multi-pass shader approach where you render the base object with the tiled stone texture in the first pass and on top render the decal passes with different shaders and different detail textures with seperate transparent alpha maps.
(Transparent map could also be stored in your detail texture, but keeping it seperate allows different tile-levels and more flexibility in reusing it.)
Additionally you can use different texture coordinate channels for each decal pass one so that you do not need to hardcode your tile level.
So for minimum you need two shaders, whereas Shader 2 is used as often as decals you need.
Shader to render tiled base texture
Shader to render one tiled detail texture using a seperate transparency map.
If you have multiple decals z-fighting can occur and you should offset your polygons a little. (Very similar to basic simple fur rendering.)
Else you need a single shader which takes multiple textures and lays them on top of the base tiled texture, this solution is less flexible, but you can use one texture for the mix between the textures (equals your 2D-array).

Resources