diff --git a/LICENSE b/LICENSE index d10d936..b6c04fb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Andres Hernandez +Copyright (c) 2022 Andres Hernandez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a960def..8c5720f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Godot Stereo 3D : Add-On For Godot Engine -Godot Stereo 3D adds stereoscopic 3D support to Godot Engine (red/cyan anaglyph 3D glasses) in game and in editor. Works as a screen-space shader based on the depth buffer (2D to 3D conversion) so is very fast. Requires GLES3. The best 3D glasses to use with this add-on are called Pro-Ana (red/cyan). They make plastic and paper versions and are very affordable. +Godot Stereo 3D adds stereoscopic 3D support to Godot Engine (red/cyan anaglyph 3D glasses) in game and in editor. Works as a screen-space shader based on the depth buffer (2D to 3D conversion) so is very fast. Requires GLES3. The best 3D glasses to use with this add-on are called Pro-Ana (red/cyan). They make plastic and paper versions and are very affordable. Proview and Anachrome glasses also work well (red/cyan). ![Screenshot](ScreenShots/Godot_Stereo_3D_Game.jpg) @@ -14,16 +14,15 @@ For manual install, download the `Stereo3D` folder from this repository and copy ## CONFIGURATION * Place the `Stereo3D.tscn` scene inside your main game tree. -* If used in combination with `Godot Super Scaling`, the `Stereo3D` node should be inside your game world. * In the `Stereo3D` inspector settings, check the `Enable` box to turn stereo on or off in game or in editor. * Set `Z Near` to the z_near of your camera. * Set `Z Far` to the z_far of your camera. -* The `Separation` controls the distance between the eyes. `0` is no distance and `100` is the maximum. -* Setting `Separation` too high may cause discomfort, so leaving it around the default of `50` is recommended. -* The `Convergence` controls the distance to the parallax plane the eyes are focused on (on the z axis). -* Higher values for `Convergence` will result in a greater 3D effect, but setting it too high may cause discomfort. -* The `Pop Out` setting controls the overlap between the left/right images. This makes the image more 3D or more comfortable. -* Typically lower `Pop Out` settings are easier to focus on. However, if you use transparent surfaces or reflections (e.g. glass windows) then it is better to set `Pop Out` to the maximum so that the transparent pass closer matches the 3D render. +* The `Stereo Strength` controls the distance between the eyes. `0` is no distance and `100` is the maximum. +* Setting `Stereo Strength` too high may cause discomfort, so leaving it around the default of `50` is recommended. +* The `Parallax Depth` controls the distance to the parallax plane the eyes are focused on (on the z axis). +* Higher values for `Parallax Depth` will result in a greater 3D effect, but setting it too high may cause discomfort. +* The `Parallax Offset` setting controls the overlap between the left/right images. This makes the image more 3D or more comfortable. +* Typically higher `Parallax Offset` settings are easier to focus on. However, it can depend on the content. * If you have overlapping transparent surfaces in your game, you need to set the `Render Priority` of the transparent material to `1` or above (for example, in a racing game, viewed from the 3rd person, the front window could have `Render Priority` of `0` and the back `1`). * For cut-out textures (like decals or grass) the `Render Priority` should be above `0`, the `Depth Draw Mode` set to `Opaque Pre-Pass`, `Transparent` set to false, and enable `Use Alpha Scissor` on the material. If the decal texture is on top of a transparent material (e.g. a sticker on a window) then the `Depth Draw Mode` must be set to `Never`. * If you use reflection probes, the reflections will be captured with the results of the post-process and will be incorrect. In these cases, you should leave the `Stereo3D` disabled in game, then on _ready() in your game, wait a certain amount of time (enough for the captures to take place) before enabling `Stereo3D`. @@ -34,7 +33,7 @@ For manual install, download the `Stereo3D` folder from this repository and copy MIT License -Copyright (c) 2021 Andres Hernandez +Copyright (c) 2022 Andres Hernandez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/ScreenShots/Godot_Stereo_3D_Game.jpg b/ScreenShots/Godot_Stereo_3D_Game.jpg index 44ebf9d..7244c34 100644 Binary files a/ScreenShots/Godot_Stereo_3D_Game.jpg and b/ScreenShots/Godot_Stereo_3D_Game.jpg differ diff --git a/ScreenShots/Godot_Stereo_3D_Game_Editor.jpg b/ScreenShots/Godot_Stereo_3D_Game_Editor.jpg index 703ae6a..014bf23 100644 Binary files a/ScreenShots/Godot_Stereo_3D_Game_Editor.jpg and b/ScreenShots/Godot_Stereo_3D_Game_Editor.jpg differ diff --git a/Stereo3D/LICENSE b/Stereo3D/LICENSE index d10d936..b6c04fb 100644 --- a/Stereo3D/LICENSE +++ b/Stereo3D/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Andres Hernandez +Copyright (c) 2022 Andres Hernandez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Stereo3D/Stereo3D.gd b/Stereo3D/Stereo3D.gd index e56bfa6..66e6fc2 100644 --- a/Stereo3D/Stereo3D.gd +++ b/Stereo3D/Stereo3D.gd @@ -3,14 +3,14 @@ tool extends Spatial -# separation controls the distance between the eyes -export(float, 0.0, 100.0) var separation = 50.0 setget change_separation -# convergence controls the focus plane (distance on z axis where the eyes focus) -export(float, 0.0, 100.0) var convergence = 50.0 setget change_convergence -# pop out adjusts the overlap to be more comfortable or for more depth -export(float, 0.0, 100.0) var pop_out = 50.0 setget change_pop_out +# stereo strength controls the distance between the eyes +export(float, 0.0, 100.0) var stereo_strength = 50.0 setget change_strength +# parallax depth controls the zero plane (distance on z axis where the eyes focus) +export(float, 0.0, 100.0) var parallax_depth = 50.0 setget change_parallax_depth +# parallax offset adjusts the overlap to be more comfortable or for more depth +export(float, 0.0, 100.0) var parallax_offset = 50.0 setget change_parallax_offset # z near should match your camera node -export var z_near = 0.05 setget change_near +export var z_near = 0.1 setget change_near # z far should match your camera node export var z_far = 100.0 setget change_far # enables stereo 3D in game or editor or both, must be controlled here @@ -22,9 +22,9 @@ var shader_material func _ready(): #warning-ignore:RETURN_VALUE_DISCARDED self.connect("visibility_changed", self, "on_visible_change") - change_separation(separation) - change_convergence(convergence) - change_pop_out(pop_out) + change_strength(stereo_strength) + change_parallax_depth(parallax_depth) + change_parallax_offset(parallax_offset) change_near(z_near) change_far(z_far) change_enable(enable) @@ -35,23 +35,23 @@ func get_shader(): shader_material = get_node("Overlay").get_surface_material(0) return shader_material -# changes the separation -func change_separation(val): - separation = val - var eye_separation = separation / 40000.0 - get_shader().set_shader_param("eye_separation", eye_separation) +# changes the eye separation +func change_strength(val): + stereo_strength = val + var eye_separation = stereo_strength / 250000.0 + get_shader().set_shader_param("stereo_strength", eye_separation) -# changes the convergence -func change_convergence(val): - convergence = val - var convergence_plane = convergence / 1000.0; - get_shader().set_shader_param("convergence_plane", convergence_plane) +# changes the zero parallax plane +func change_parallax_depth(val): + parallax_depth = val + var zero_plane = parallax_depth / 100.0; + get_shader().set_shader_param("parallax_depth", zero_plane) -# changes the pop out -func change_pop_out(val): - pop_out = val - var parallax_offset = (100.0 - pop_out) / 10000.0; - get_shader().set_shader_param("parallax_offset", parallax_offset) +# changes the offset +func change_parallax_offset(val): + parallax_offset = val + var offset_amount = (100.0 - parallax_offset) / 5000.0; + get_shader().set_shader_param("parallax_offset", offset_amount) # changes if stereo 3D is enabled in game or editor func change_enable(val): diff --git a/Stereo3D/Stereo3D.tres b/Stereo3D/Stereo3D.tres index dd2882f..19267af 100644 --- a/Stereo3D/Stereo3D.tres +++ b/Stereo3D/Stereo3D.tres @@ -8,29 +8,29 @@ render_mode skip_vertex_transform, depth_test_disable, unshaded, shadows_disabled, ambient_light_disabled; // separation between the eyes -uniform float eye_separation = 0.00125; +uniform float stereo_strength = 0.0002; // focus plane on z axis -uniform float convergence_plane = 0.05; +uniform float parallax_depth = 0.5; // overlap of left/right images -uniform float parallax_offset = 0.005; +uniform float parallax_offset = 0.01; // z near of the camera -uniform float z_near = 0.05; +uniform float z_near = 0.1; // z far of the camera uniform float z_far = 100.0; // x offset for sample coordinates const float samples[3] = {0.5, 0.66, 1.0}; // count for above samples const int sample_count = 3; -// left color filter to reduce ghosting -const mat3 left_optimize = mat3( - vec3(0.437, 0.449, 0.164), - vec3(-0.062, -0.062, -0.024), - vec3(-0.048, -0.050, -0.017)); -// right color filter to reduce ghosting -const mat3 right_optimize = mat3( - vec3(-0.011, -0.032, -0.007), - vec3(0.377, 0.761, 0.009), - vec3(-0.026, -0.093, 1.234)); +// left color filter +const mat3 left_filter = mat3( + vec3(0.4561, 0.500484, 0.176381), + vec3(-0.400822, -0.0378246, -0.0157589), + vec3(-0.0152161, -0.0205971, -0.00546856)); +// right color filter +const mat3 right_filter = mat3( + vec3(-0.0434706, -0.0879388, -0.00155529), + vec3(0.378476, 0.73364, -0.0184503), + vec3(-0.0721527, -0.112961, 1.2264)); // scales the overlay to full screen void vertex() { @@ -45,15 +45,16 @@ vec3 getColor(sampler2D tex, vec2 uv) { // samples the depth from depth buffer in linear space float getDepth(sampler2D tex, vec2 uv) { - float depth_map = textureLod(tex, uv, 0.0).r * 2.0 - 1.0; - float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth_map * (z_far - z_near)); + float depth_sample = textureLod(tex, uv, 0.0).r; + float ndc = depth_sample * 2.0 - 1.0; + float linear_depth = (2.0 * z_near * z_far) / (z_far + z_near - ndc * (z_far - z_near)); linear_depth /= z_far; return linear_depth; } // get the parallax offset float getParallax(float depth) { - depth = 1.0 - convergence_plane / depth; + depth = 1.0 - parallax_depth / depth; return depth; } @@ -64,17 +65,19 @@ void fragment() { vec2 uv = vec2(0.0); for (int i = 0; i < sample_count; ++i) { - uv.x = samples[i] * eye_separation + parallax_offset; + uv.x = samples[i] * stereo_strength + parallax_offset; min_depth_left = min(min_depth_left, getDepth(DEPTH_TEXTURE, SCREEN_UV + uv)); min_depth_right = min(min_depth_right, getDepth(DEPTH_TEXTURE, SCREEN_UV - uv)); } - float parallax_left = eye_separation * getParallax(min_depth_left) + parallax_offset; - float parallax_right = eye_separation * getParallax(min_depth_right) + parallax_offset; + float parallax_left = stereo_strength * getParallax(min_depth_left) + parallax_offset; + float parallax_right = stereo_strength * getParallax(min_depth_right) + parallax_offset; vec3 color_left = getColor(SCREEN_TEXTURE, SCREEN_UV + vec2(parallax_left, 0.0)); vec3 color_right = getColor(SCREEN_TEXTURE, SCREEN_UV - vec2(parallax_right, 0.0)); - - ALBEDO = clamp(color_left * left_optimize, vec3(0.0), vec3(1.0)) + clamp(color_right * right_optimize, vec3(0.0), vec3(1.0)); + + vec3 color_final = clamp(color_left * left_filter, vec3(0.0), vec3(1.0)) + clamp(color_right * right_filter, vec3(0.0), vec3(1.0)); + + ALBEDO = color_final; } " diff --git a/Stereo3D/Stereo3D.tscn b/Stereo3D/Stereo3D.tscn index 400c686..354f240 100644 --- a/Stereo3D/Stereo3D.tscn +++ b/Stereo3D/Stereo3D.tscn @@ -9,10 +9,10 @@ size = Vector2( 2, 2 ) [sub_resource type="ShaderMaterial" id=3] render_priority = -128 shader = ExtResource( 2 ) -shader_param/eye_separation = 0.00125 -shader_param/convergence_plane = 0.05 -shader_param/parallax_offset = 0.005 -shader_param/z_near = 0.05 +shader_param/stereo_strength = 0.0002 +shader_param/parallax_depth = 1.0 +shader_param/parallax_offset = 0.01 +shader_param/z_near = 0.1 shader_param/z_far = 100.0 [node name="Stereo3D" type="Spatial"]