Created
April 9, 2019 02:13
-
-
Save clayjohn/38f669030c9921ac176b6fa2a9ea86b2 to your computer and use it in GitHub Desktop.
Convert cubemap to panorama in 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 sampler2D front; | |
uniform sampler2D left; | |
uniform sampler2D right; | |
uniform sampler2D back; | |
uniform sampler2D top; | |
uniform sampler2D bottom; | |
void fragment() { | |
COLOR.x = 1.0; | |
float theta = UV.y*3.14159; | |
float phi = UV.x*3.14159*2.0; | |
vec3 unit = vec3(0,0,0); | |
unit.x = sin(phi) * sin(theta) * -1.0; | |
unit.y = cos(theta) * -1.0; | |
unit.z = cos(phi) * sin(theta) * -1.0; | |
unit = normalize(unit); | |
vec2 st = vec2(0.0); | |
if (-unit.y>=abs(unit.x) && -unit.y>=abs(unit.z)) { | |
st = ((vec2(1.0, -1.0)*unit.xz)/abs(unit.y)+1.0)/2.0; | |
COLOR = texture(bottom, st); | |
} if (unit.y>=abs(unit.x) && unit.y>=abs(unit.z)) { | |
st = ((unit.xz)/abs(unit.y)+1.0)/2.0; | |
COLOR = texture(top, st); | |
} if (unit.x>=abs(unit.y) && unit.x>=abs(unit.z)) { | |
st = (-unit.zy/abs(unit.x)+1.0)/2.0; | |
COLOR = texture(left, st); | |
} if (-unit.x>=abs(unit.y) && -unit.x>=abs(unit.z)) { | |
st = ((vec2(1.0, -1.0)*unit.zy)/abs(unit.x)+1.0)/2.0; | |
COLOR = texture(right, st); | |
} if (unit.z>=abs(unit.x) && unit.z>=abs(unit.y)) { | |
st = ((vec2(1.0, -1.0)*unit.xy)/abs(unit.z)+1.0)/2.0; | |
COLOR = texture(back, st); | |
} if (-unit.z>=abs(unit.x) && -unit.z>=abs(unit.y)) { | |
st = ((vec2(-1.0)*unit.xy)/abs(unit.z)+1.0)/2.0; | |
COLOR = texture(front, st); | |
} | |
} | |
/* | |
in GDscript | |
# attach all faces | |
for key in faces: | |
$Viewport/ColorRect.material.set_shader_param(key, faces[key]) | |
#Update once next frame | |
$Viewport.render_target_update_mode = Viewport.UPDATE_ONCE | |
#wait until next frame | |
yield(get_tree(), "idle_frame") | |
var texture_data = $Viewport2.get_texture().get_data() | |
var panorama = ImageTexture.new() | |
panorama.create_from_image(texture_data) | |
*/ |
It is a dictionary where the key is "front", "left" etc. and the value is the corresponding ImageTexture.
Here is the full code for reference, it's not as easy to understand but it contains everything I used.
extends Spatial
var faces = {}
# Called when the node enters the scene tree for the first time.
func _ready():
#wait until objects in frame
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
#render cubemap
render_face("front", 0.0)
yield(get_tree(), "idle_frame")
render_face("left", PI/2)
yield(get_tree(), "idle_frame")
render_face("back", PI)
yield(get_tree(), "idle_frame")
render_face("right", 3.0*PI/2.0)
yield(get_tree(), "idle_frame")
render_face("top", PI, PI/2.0)
yield(get_tree(), "idle_frame")
render_face("bottom", PI, -PI/2.0)
#Render panorama sky
yield(get_tree(), "idle_frame")
for key in faces:
$Viewport2/ColorRect.material.set_shader_param(key, faces[key])
$Viewport2.render_target_update_mode = Viewport.UPDATE_ONCE
yield(get_tree(), "idle_frame")
var td = $Viewport2.get_texture().get_data()
var gg = ImageTexture.new()
gg.create_from_image(td)
#Attach panorama sky
var we = WorldEnvironment.new()
var wee = Environment.new()
wee.background_mode = Environment.BG_SKY
wee.background_sky = PanoramaSky.new()
wee.background_sky.panorama = gg
we.environment = wee
add_child(we)
func render_face(face, diry, dirx = 0.0):
$Viewport/Camera.rotation.y = diry
$Viewport/Camera.rotation.x = dirx
yield(get_tree(), "idle_frame")
faces[face] = ImageTexture.new()
faces[face].create_from_image($Viewport.get_texture().get_data())
faces[face].flags = 0
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In the GDscript, is
faces
an enum offront, left, right, back, top, bottom
or...?