Created
January 2, 2020 22:42
-
-
Save Jellonator/0686c6e74d06745957de5a96fa00ec6c to your computer and use it in GitHub Desktop.
Mode 7 shader for Godot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
shader_type canvas_item; | |
uniform mat4 TRANSFORM; | |
uniform vec2 DEPTH; | |
uniform bool REPEAT_X; | |
uniform bool REPEAT_Y; | |
uniform bool FLIP; | |
void fragment() { | |
// Create the matrix. A workaround is used to modify the matrix's W column | |
// because Godot's transforms are 3x4, not 4x4. | |
mat4 mat = mat4(1.0); | |
mat[0].w = DEPTH.x; | |
mat[1].w = DEPTH.y; | |
// Transform UV into [-1, 1] range | |
vec2 uv = UV * 2.0 - vec2(1, 1); | |
// Turn position into 4d vector | |
vec4 pos = vec4(uv, 1.0, 1.0); | |
pos = mat * pos; | |
pos.xy = pos.xy / pos.w; | |
// Apply transformation to position | |
float w = pos.w; | |
pos.z = 0.0; | |
pos.w = 1.0; | |
// Apply depth to position | |
pos = TRANSFORM * pos; | |
// divide position by w coordinate; this applies perspective | |
// Set UV to position; transform its range to [0, 1] | |
uv = (pos.xy + vec2(1, 1)) * 0.5; | |
// Determine if uv is in range or repeating pattern | |
if (((uv.x > 0.0 && uv.x < 1.0) || REPEAT_X) && ((uv.y > 0.0 && uv.y < 1.0) || REPEAT_Y) && (w > 0.0 || FLIP)) { | |
// Apply texture | |
uv = mod(uv, 1.0); | |
COLOR = texture(TEXTURE, uv); | |
} else { | |
COLOR = vec4(0, 0, 0, 0); | |
} | |
} |
Sharing here before I forgot. I was just able to get the above code to work in C# with some slight changes. Working on some other touches now but the only way I was able to wrap my head around the entire thing and understand it properly was to use the Systems.Numerics and convert it all to a Matrix4x4.
// good luck with the below
using Godot;
using System;
using System.Numerics;
public class object_test : Node2D
{
Godot.ShaderMaterial mode7;
Godot.Node2D parent;
Godot.Sprite spriteToMove;
private Matrix4x4 perspectiveMatrix = new Matrix4x4();
private Matrix4x4 viewMatrix = new Matrix4x4();
private Godot.Vector2 screenSize = new Godot.Vector2(1024,1024);
private float halfHeight = 512;
public override void _Ready()
{
parent = GetParent() as Node2D;
mode7 = parent.Material as ShaderMaterial;
spriteToMove = GetNode<Sprite>("Sprite");
Godot.Vector2 temp = new Godot.Vector2(0, 20);
Create2DPerspectiveMatrix(temp);
}
private void Create2DPerspectiveMatrix(Godot.Vector2 depth)
{
Vector4 _line1 = new Vector4(1f, 0f, 0f, depth.x);
Vector4 _line2 = new Vector4(0f, 1f, 0f, depth.y);
Vector4 _line3 = new Vector4(0f, 0f, 1f, 0f);
Vector4 _line4 = new Vector4(0f, 0f, 0f, 1f);
perspectiveMatrix.M11 = _line1.X;
perspectiveMatrix.M12 = _line1.Y;
perspectiveMatrix.M13 = _line1.Z;
perspectiveMatrix.M14 = _line1.W;
perspectiveMatrix.M21 = _line2.X;
perspectiveMatrix.M22 = _line2.Y;
perspectiveMatrix.M23 = _line2.Z;
perspectiveMatrix.M24 = _line2.W;
perspectiveMatrix.M31 = _line3.X;
perspectiveMatrix.M32 = _line3.Y;
perspectiveMatrix.M33 = _line3.Z;
perspectiveMatrix.M34 = _line3.W;
perspectiveMatrix.M41 = _line4.X;
perspectiveMatrix.M42 = _line4.Y;
perspectiveMatrix.M43 = _line4.Z;
perspectiveMatrix.M44 = _line4.W;
}
private void CreateViewMatrix(Godot.Transform _transform, Godot.Vector2 _depth)
{
Vector4 _line1 = new Vector4(_transform.basis.x.x, _transform.basis.x.y, _transform.basis.x.z, 0f);
Vector4 _line2 = new Vector4(_transform.basis.y.x, _transform.basis.y.y, _transform.basis.y.z, 0f);
Vector4 _line3 = new Vector4(_transform.basis.z.x, _transform.basis.z.y, _transform.basis.z.z, 0f);
Vector4 _line4 = new Vector4(_transform.origin.x, _transform.origin.y, 0f, 1f);
viewMatrix.M11 = _line1.X;
viewMatrix.M12 = _line1.Y;
viewMatrix.M13 = _line1.Z;
viewMatrix.M14 = _line1.W;
viewMatrix.M21 = _line2.X;
viewMatrix.M22 = _line2.Y;
viewMatrix.M23 = _line2.Z;
viewMatrix.M24 = _line2.W;
viewMatrix.M31 = _line3.X;
viewMatrix.M32 = _line3.Y;
viewMatrix.M33 = _line3.Z;
viewMatrix.M34 = _line3.W;
viewMatrix.M41 = _line4.X;
viewMatrix.M42 = _line4.Y;
viewMatrix.M43 = _line4.Z;
viewMatrix.M44 = _line4.W;
}
public Godot.Vector3 MultPositionByVect4(Godot.Vector2 worldPos, Matrix4x4 mat)
{
Vector4 temp = new Vector4(worldPos.x, worldPos.y, 0f, 1f);
Vector4 _transformed = Vector4.Transform(temp, mat);
Godot.Vector3 _newReturn = new Godot.Vector3(_transformed.X / _transformed.W, _transformed.Y / _transformed.W, _transformed.W);
return _newReturn;
}
public override void _Process(float delta)
{
Godot.Transform _transform = (Godot.Transform)mode7.GetShaderParam("TRANSFORM");
GD.Print(_transform);
Godot.Vector2 _depth = (Godot.Vector2)mode7.GetShaderParam("DEPTH");
Create2DPerspectiveMatrix(_depth);
CreateViewMatrix(_transform, _depth);
Matrix4x4 _mat = perspectiveMatrix * viewMatrix;
//Matrix4x4 _mat = viewMatrix * perspectiveMatrix;
Matrix4x4 _inverted = new Matrix4x4();
Matrix4x4.Invert(_mat, out _inverted);
//Matrix4x4 _mat = viewMatrix * perspectiveMatrix;
//Godot.Vector2 worldPos = (this.GlobalPosition / (screenSize / 2)) - Godot.Vector2.One;
float wX = this.GlobalPosition.x;
float xY = this.GlobalPosition.y;
Godot.Vector2 worldpos = (this.GlobalPosition / (screenSize / 2)) - Godot.Vector2.One;
Godot.Vector3 newPos = MultPositionByVect4(worldpos, _inverted);
Godot.Vector2 final = new Godot.Vector2(newPos.x, newPos.y);
//Godot.Vector2 finalPos = new Godot.Vector2(newPos.x, newPos.y);
//Godot.Vector2 finalPos1 = new Godot.Vector2(finalPos + Godot.Vector2.One) * (screenSize / 2);
spriteToMove.GlobalPosition = (final + Godot.Vector2.One) * (screenSize / 2);
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm close to getting this to work, I think? I'm translating it over to C# though and might have fumbled a few things and I'm also doing some questionable things with Viewports where I create a copy of the objects I want to display with the mode 7 and leave the originals to keep game logic completely 2D. I'll put the project link below if you wanted to look, otherwise I'll report back as I attempt to figure out what I messed up.
https://github.com/DTFlip/Mode7_Godot