Looking for a 2D perspective view of a wall or a roof whithout a 3D object? You can try this!

rotation_angle:Adjust the angle of its rotation. In the cover image, there are 4 planes which are all 1.57(pi/2) rotated, which means they are straightly forwarded inside and the camera is at center.

isVertical:Tick it if it is a wall! Don’t tick it if it is a roof or floor.

isBottomOrLeftLonger:Tick it if it is a leftwall/floor, which has a wider edge on left/bottom side.

viewPosition:The offset of viewer from the center.eg. (-0.1,-0.2)means move the camera 0.1 left and 0.2 down

thickness:Control the depth of the wall or roof/floor

(3 Sep,2024 updated)

``````#define pi 3.14159265358979323

uniform float rotationAngle;
uniform bool isVertical;
uniform bool isLeftOrBottomLonger;
uniform vec2 viewPosition;
uniform float thickness=0.5;

struct ray{
vec3 o,d;
};

ray GetRay(vec2 uv, vec3 camPos, vec3 lookAt, float zoom){
ray a;
a.o = camPos;

vec3 f = normalize(lookAt-camPos);
vec3 r = normalize(cross(vec3(0.0,1.0,0.0),f));
vec3 u = cross(f,r);
vec3 c = camPos + f * zoom;
vec3 i;
i = vec3(0.,0.,1.)+uv.x*vec3(0.,1.,0.)+uv.y*vec3(1.,0.,0.);
//i = c + uv.x * u + uv.y * r;

a.d = normalize(i-a.o);

return a;
}

void vertex() {
// Called for every vertex the material is visible on.
}

void fragment() {
vec2 uv=2.*(UV-.5);
vec3 camPos = vec3(viewPosition.y,viewPosition.x,0.0);
vec3 lookAt = vec3(viewPosition.y,viewPosition.x,1.0);

ray r = GetRay(uv, camPos, lookAt, 1.0);

float rotat = rotationAngle;
//describe the plane
vec3 tar_point;
vec3 tar_normal;
if(isVertical){
if(isLeftOrBottomLonger){
tar_point=vec3(-1.0,-1.0,1.0);
tar_normal=vec3(0.0,sin(rotat),-cos(rotat));
}else{
tar_point=vec3(1.0,1.0,1.0);
tar_normal=vec3(0.0,-sin(rotat),-cos(rotat));
}
}else{
if(isLeftOrBottomLonger){
tar_point=vec3(-1.0,-1.0,1.0);
tar_normal=vec3(sin(rotat),0.,-cos(rotat));
}else{
tar_point=vec3(1.0,1.0,1.0);
tar_normal=vec3(-sin(rotat),0.,-cos(rotat));
}
}

float dividend=dot(tar_normal,(tar_point-r.o));
float divider=dot(tar_normal,r.d);
float t=0.0;
vec3 col=vec3(0.0);
vec3 hitPoint;
vec3 text_xy_10_point;
vec3 text_xy_11_point;
vec3 text_xy_01_point;
vec3 text_xy_00_point;
float text_x_bound=4.0;
float text_y_bound=4.0;
if (abs(divider)>=1e-6 && abs(dividend)>=1e-6)
{
t=dividend/divider;
hitPoint=r.o+t*r.d;
if(isVertical){
if(isLeftOrBottomLonger){
text_xy_10_point=vec3(-1.0,thickness*2.*cos(rotat)-1.0,1.0+thickness*2.*sin(rotat));
text_xy_11_point=vec3(1.0,thickness*2.*cos(rotat)-1.0,1.0+thickness*2.*sin(rotat));
text_xy_01_point=vec3(1.0,-1.0,1.0);
text_xy_00_point=vec3(-1.0,-1.0,1.0);
text_x_bound*=thickness*thickness;
}else{
text_xy_10_point=vec3(-1.0,1.0,1.0);
text_xy_11_point=vec3(1.0,1.0,1.0);
text_xy_01_point=vec3(1.0,1.-thickness*2.*cos(rotat),1.0+thickness*2.*sin(rotat));
text_xy_00_point=vec3(-1.0,1.-thickness*2.*cos(rotat),1.0+thickness*2.*sin(rotat));
text_x_bound*=thickness*thickness;
}
}else{
if(isLeftOrBottomLonger){
text_xy_10_point=vec3(-1.0,1.0,1.0);
text_xy_11_point=vec3(thickness*2.*cos(rotat)-1.,1.0,1.0+thickness*2.*sin(rotat));
text_xy_01_point=vec3(thickness*2.*cos(rotat)-1.,-1.0,1.0+thickness*2.*sin(rotat));
text_xy_00_point=vec3(-1.0,-1.0,1.0);
text_y_bound*=thickness*thickness;
}else{
text_xy_10_point=vec3(1.-thickness*2.*cos(rotat),1.0,1.0+thickness*2.*sin(rotat));
text_xy_11_point=vec3(1.0,1.0,1.0);
text_xy_01_point=vec3(1.0,-1.0,1.0);
text_xy_00_point=vec3(1.-thickness*2.*cos(rotat),-1.0,1.0+thickness*2.*sin(rotat));
text_y_bound*=thickness*thickness;
}
}
float text_x=dot((hitPoint-text_xy_00_point),(text_xy_10_point-text_xy_00_point));
float text_y=dot((hitPoint-text_xy_00_point),(text_xy_01_point-text_xy_00_point));
if(text_x<text_x_bound && text_y<text_y_bound && text_x>0.0 && text_y>0.0)
{
vec2 tex_coord=vec2(text_x,text_y);
tex_coord/=4.0;
if(isVertical){
tex_coord.x/=thickness*thickness;
}else{
tex_coord.y/=thickness*thickness;
}
col=vec3(texture(TEXTURE,tex_coord).x);
}
else{
COLOR.a=0.0;
}
}
else{
COLOR.a=0.0;
}
// Output to screen
COLOR.xyz = col;
// Called for every pixel the material is visible on.
}

//void light() {
// Called for every pixel for every light affecting the CanvasItem.
// Uncomment to replace the default light processing function with this one.
//}
``````
###### Tags
2d, perspective
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.