Fake 3D Interior Projection Shader Fixed & Adjustable

This shader has been carefully calibrated with specific offset and scale values that maximize atlas texture utilization. Each face’s parameters are tuned to extract room details perfectly from the texture grid, eliminating common issues like misalignment or improper scaling for realistic interior projection.

Based on: “Interior mapping shader” by AndreaTerenz (September 6, 2022) from https://godotshaders.com/shader/interior-mapping-shader/

What’s Fixed & Improved:

  • Parameterized offsets & scales – All face properties are now exposed as uniform arrays for easy tuning
  • Fixed UV calculation – Corrected both axes flipping for proper texture orientation
  • Added texture clamping – Prevents sampling artifacts at atlas edges
  • Cleaner face detection – Streamlined logic while maintaining accuracy
  • Configurable layout – Each face (+X, -X, +Y, -Y, +Z, -Z) can be independently adjusted

How to Use:

  1. Apply to: MeshInstance3D (recommended mesh: QuadMesh or PlaneMesh)
  2. Set up:
    • Use the included texture templates for consistent results
    • Adjust Z-scale to control interior depth (higher values = deeper rooms)
    • Configure each face’s face_offset and face_size in the material inspector
  3. Texture: Apply your room atlas to the room_atlas uniform
  4. Face Configuration:
    • Index 0: +X face (right wall)
    • Index 1: -X face (left wall)
    • Index 2: +Y face (top/ceiling)
    • Index 3: -Y face (bottom/floor)
    • Index 4: +Z face (back wall)
    • Index 5: -Z face (front wall)

Best Use Cases:

  • Mass building optimization – Replace thousands of detailed meshes with simple planes
  • Cityscapes – Add interior detail to distant buildings without performance cost
  • Game jams – Quick interior setups for windows and buildings
  • Retro/PSX style – Combine with pixel art textures for aesthetic results
  • Custom room layouts – Adjust each wall independently for unique interiors

Texture Templates:

Template textures are provided with standardized layouts:

  • 6-face atlas with consistent sizing
  • Grid-based organization for easy editing
  • Marker guides for face alignment
  • Compatible with parameterized offsets – easy to match custom layouts

Technical Details:

  • Render Mode: Unshaded (full control over appearance)
  • Algorithm: Ray-box intersection with per-face UV mapping
  • Parameters: Exposed uniform arrays for complete control
  • Performance: Extremely lightweight – suitable for hundreds of instances
  • Compatibility: Godot 4.0+ (spatial shader)
  • Flexibility: Each face can have unique scaling and positioning

Reference Values:

  • Offset Values:
    • Index 0 (+X face): -0.340, 0.75
    • Index 1 (-X face): -0.675, -0.75
    • Index 2 (+Y face): 0.1775, -0.5
    • Index 3 (-Y face): 0.1775, 0.5
    • Index 4 (+Z face): 0.0, 0.0
    • Index 5 (-Z face): 0.515, -0.25
  • Size Values:
    • Index 0 (+X face): 1.35, 1.0
    • Index 1 (-X face): 1.35, 1.0
    • Index 2 (+Y face): 0.65, 2.0
    • Index 3 (-Y face): 0.65, 2.0
    • Index 4 (+Z face): 1.0, 1.0
    • Index 5 (-Z face): 0.65, 1.0
Shader code
// MIT License
// 
// Copyright (c) 2026 [PROJEKTSANSSTUDIOS]
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Configurable Fake 3D Interior Shader
// Description: Creates a 3D interior illusion with customizable face parameters

shader_type spatial;
render_mode unshaded;

uniform sampler2D room_atlas;
uniform float brightness : hint_range(0.0, 4.0) = 1.0; // Brightness control clamped 0-4

/* 0:+X  1:-X  2:+Y  3:-Y  4:+Z  5:-Z */
uniform vec2 face_offset[6];
uniform vec2 face_size[6];

varying vec3 v_pos;
varying vec3 v_cam;

vec2 face_uv(vec3 p, vec3 f) {
	if (f.x > 0.5)  return vec2(-p.z,  p.y);
	if (f.x < -0.5) return vec2( p.z,  p.y);
	if (f.y > 0.5)  return vec2( p.x, -p.z);
	if (f.y < -0.5) return vec2( p.x,  p.z);
	if (f.z > 0.5)  return vec2( p.x,  p.y);
	return vec2(-p.x,  p.y);
}

int face_index(vec3 f) {
	if (f.x > 0.5)  return 0;
	if (f.x < -0.5) return 1;
	if (f.y > 0.5)  return 2;
	if (f.y < -0.5) return 3;
	if (f.z > 0.5)  return 4;
	return 5;
}

void vertex() {
	v_pos = VERTEX;
	v_cam = inverse(MODELVIEW_MATRIX)[3].xyz;
}

void fragment() {
	vec3 ray = normalize(v_pos - v_cam);

	float tx = (ray.x > 0.0) ? (0.5 - v_cam.x) / ray.x : (-0.5 - v_cam.x) / ray.x;
	float ty = (ray.y > 0.0) ? (0.5 - v_cam.y) / ray.y : (-0.5 - v_cam.y) / ray.y;
	float tz = (ray.z > 0.0) ? (0.5 - v_cam.z) / ray.z : (-0.5 - v_cam.z) / ray.z;

	float t = min(min(tx, ty), tz);
	vec3 hit = v_cam + ray * t;

	vec3 face;
	if (t == tx) face = vec3(sign(ray.x), 0.0, 0.0);
	else if (t == ty) face = vec3(0.0, sign(ray.y), 0.0);
	else face = vec3(0.0, 0.0, sign(ray.z));

	vec2 uv = face_uv(hit, face) * 0.5 + 0.5;

	/* FIX: flip both axes */
	uv = vec2(1.0 - uv.x, 1.0 - uv.y);

	uv = clamp(uv, 0.0, 1.0);

	int i = face_index(face);
	vec2 atlas_uv = face_offset[i] + uv * face_size[i];

	// Sample texture and apply brightness
	vec3 color = texture(room_atlas, atlas_uv).rgb;
	
	// Apply brightness control
	color = color * brightness;
	
	// Clamp to prevent negative values
	color = max(color, 0.0);
	
	ALBEDO = color;
}
Live Preview
Tags
buildings, fake, fake interior, house, interior, interior shader, parallax, parallax mirror, room interior, shader
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Lord0Sanz

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments