Last active
November 7, 2024 22:29
-
-
Save partybusiness/d7594590435217214d9d7d34c7dc9e34 to your computer and use it in GitHub Desktop.
This file contains 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
@tool | |
extends EditorScript | |
# converts an equirectangular panoramic texture to a skyamid format | |
var source_panorama:String = "res://skybox_example_pano_left.png" | |
var target_skyamid:String = "res://skyamid.png" | |
func _run() -> void: | |
# load source | |
var source:Image = Image.load_from_file(source_panorama) | |
var new_image:Image = Image.create(source.get_height(), source.get_height(), false, source.get_format()) | |
#source.get_height() | |
var last_average:Color = Color.BLACK | |
var half_size:int = source.get_height()/2 | |
var quadrant_size:int = source.get_width()/4 | |
for ty in range(0, half_size): | |
last_average = Color.MAGENTA | |
last_average.a = 0.0 | |
for quad_index in range(0, 4): # per quadrant | |
for tx in range(-ty, ty): | |
var get_average:Color = Color.BLACK | |
get_average.a = 0 | |
var count:int = 0 | |
var quadrant_offset:int = quad_index * quadrant_size - quadrant_size * 0.5 + source.get_width() + 1 # offset to make it match original sky | |
var vx:int = (float(tx) / (float(ty) * 2.0) + 0.5) * float(quadrant_size) | |
var vx2:int = (float(tx+1.0) / (float(ty) * 2.0) + 0.5) * float(quadrant_size) | |
var y_offset:Vector2i = Vector2i(0, 0) | |
var x_offset:Vector2i = Vector2i(0, 0) | |
match quad_index: | |
0: | |
y_offset = Vector2i(0, -1) | |
x_offset = Vector2i(1, 0) | |
1: | |
y_offset = Vector2i(1, 0) | |
x_offset = Vector2i(0, 1) | |
2: | |
y_offset = Vector2i(0, 1) | |
x_offset = Vector2i(-1, 0) | |
3: | |
y_offset = Vector2i(-1, 0) | |
x_offset = Vector2i(0, -1) | |
for avx in range(vx, vx2): | |
get_average += source.get_pixel( (avx + quadrant_offset) % source.get_width(), ty) | |
count += 1 | |
if count == 0: # this will happen if panorama source is less than twice the height | |
new_image.set_pixel( | |
half_size + tx * x_offset.x + ty * y_offset.x, | |
half_size + tx * x_offset.y + ty * y_offset.y, last_average) | |
else: | |
get_average /= float(count) | |
new_image.set_pixel( | |
half_size + tx * x_offset.x + ty * y_offset.x, | |
half_size + tx * x_offset.y + ty * y_offset.y, get_average) | |
last_average = get_average | |
#fill in transparent pixels from neighbours | |
for x in range(0, new_image.get_width()): | |
for y in range(0, new_image.get_height()): | |
var test_colour:Color = new_image.get_pixel(x,y) | |
if test_colour.a < 0.01: | |
var get_average:Color = Color.BLACK | |
var count:int =0 | |
get_average.a = 0.0 | |
var sample:Color = new_image.get_pixel(clamp(x+1, 0, new_image.get_width()-1), y) | |
if sample.a >= 0.1: | |
get_average += sample | |
count += 1 | |
sample = new_image.get_pixel(clamp(x-1, 0, new_image.get_width()-1), y) | |
if sample.a >= 0.1: | |
get_average += sample | |
count += 1 | |
sample = new_image.get_pixel(x, clamp(y+1, 0, new_image.get_height()-1)) | |
if sample.a >= 0.1: | |
get_average += sample | |
count += 1 | |
sample = new_image.get_pixel(x, clamp(y-1, 0, new_image.get_height()-1)) | |
if sample.a >= 0.1: | |
get_average += sample | |
count += 1 | |
if (count > 0): | |
get_average /= float(count) | |
new_image.set_pixel(x, y, get_average) | |
#save result | |
new_image.save_png(target_skyamid) |
This file contains 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 sky; | |
uniform sampler2D skyTexture:source_color; | |
vec2 get_skyamid_uv(vec3 eyedir) { | |
float ax = abs(eyedir.x); | |
float xs = sign(eyedir.x); | |
float az = abs(eyedir.z); | |
float zs = sign(eyedir.z); | |
float ay = abs(eyedir.y); | |
float y = 1.0 - atan(ay, length(vec2(ax,az))) / 1.5708; | |
float x = 0.0; | |
if (ax > az) { | |
x = xs * atan(eyedir.z, ax) / 1.5708; | |
return vec2(0.5 + y * 0.5 * xs, 0.5 + y * x * xs); | |
} | |
else { | |
x = zs * atan(eyedir.x, az) / 1.5708; | |
return vec2(0.5 + y * x * zs, 0.5 + y * 0.5 * zs); | |
} | |
} | |
void sky() { | |
vec2 uv = get_skyamid_uv(EYEDIR); | |
COLOR = texture(skyTexture, uv).rgb; | |
} |
This file contains 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 spatial; | |
render_mode unshaded; | |
uniform sampler2D skyTexture:source_color; | |
vec2 get_skyamid_uv(vec3 eyedir) { | |
float ax = abs(eyedir.x); | |
float xs = sign(eyedir.x); | |
float az = abs(eyedir.z); | |
float zs = sign(eyedir.z); | |
float ay = abs(eyedir.y); | |
float y = 1.0 - atan(ay, length(vec2(ax,az))) / 1.5708; | |
float x = 0.0; | |
if (ax > az) { | |
x = xs * atan(eyedir.z, ax) / 1.5708; | |
return vec2(0.5 + y * 0.5 * xs, 0.5 + y * x * xs); | |
} | |
else { | |
x = zs * atan(eyedir.x, az) / 1.5708; | |
return vec2(0.5 + y * x * zs, 0.5 + y * 0.5 * zs); | |
} | |
} | |
varying vec3 world_position; | |
void vertex() | |
{ | |
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; | |
} | |
void fragment() { | |
vec3 view_dir = normalize(world_position - CAMERA_POSITION_WORLD); | |
vec2 uv = get_skyamid_uv(view_dir); | |
ALBEDO = texture(skyTexture, uv).rgb; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment