Skip to content

Instantly share code, notes, and snippets.

@jasonphillips
Last active April 6, 2020 06:52
Show Gist options
  • Save jasonphillips/4cc91e85f128eae4f086118a59241ca1 to your computer and use it in GitHub Desktop.
Save jasonphillips/4cc91e85f128eae4f086118a59241ca1 to your computer and use it in GitHub Desktop.
Lens distortion for Dolphin emulator (for VR viewers) as custom shader
/*
[configuration]
[OptionRangeInteger]
GUIName = Distortion amount
OptionName = DISTORTION_FACTOR
MinValue = 1
MaxValue = 10
StepAmount = 1
DefaultValue = 4
[OptionRangeInteger]
GUIName = Eye Distance Offset
OptionName = EYE_OFFSET
MinValue = 0
MaxValue = 10
StepAmount = 1
DefaultValue = 5
[OptionRangeFloat]
GUIName = Zoom adjustment
OptionName = SIZE_ADJUST
MinValue = 0.0
MaxValue = 1.0
StepAmount = 0.1
DefaultValue = 0.5
[OptionRangeFloat]
GUIName = Aspect Ratio adjustment
OptionName = ASPECT_ADJUST
MinValue = 0.0
MaxValue = 1.0
StepAmount = 0.1
DefaultValue = 0.5
[/configuration]
*/
void main() {
// Base Cardboard distortion parameters
float factor = GetOption(DISTORTION_FACTOR) * 0.01f;
float ka = factor * 3.0f;
float kb = factor * 5.0f;
float sizeAdjust = 1.0f - GetOption(SIZE_ADJUST) + 0.5f;
float aspectAdjustment = 1.25f - GetOption(ASPECT_ADJUST);
// offset centering per eye
float stereoOffset = GetOption(EYE_OFFSET) * 0.01f;
float offsetAdd;
// layer0 = left eye, layer1 = right eye
if (layer == 1) {
offsetAdd = stereoOffset;
} else {
offsetAdd = 0 - stereoOffset;
}
// convert coordinates to NDC space
float2 fragPos = (GetCoordinates() - 0.5f - vec2(offsetAdd, 0.0f)) * 2.0f;
// Calculate the source location "radius" (distance from the centre of the viewport)
float destR = length(fragPos);
float srcR = destR * sizeAdjust + ( ka * pow(destR,2) + kb * pow(destR,4));
// Calculate the source vector (radial)
vec2 correctedRadial = normalize(fragPos) * srcR;
// fix aspect ratio
vec2 widenedRadial = correctedRadial * vec2(aspectAdjustment, 1.0f);
// Transform the coordinates (from [-1,1]^2 to [0, 1]^2)
vec2 uv = (widenedRadial/2.0f) + vec2(0.5f) + vec2(offsetAdd, 0.0f);
// Sample the texture at the source location
if (uv[0] > 1.0 || uv[1] > 1.0 || uv[0] < 0.0 || uv[1] < 0.0) {
// black if beyond bounds
SetOutput(float4(0,0,0,0));
} else {
SetOutput(SampleLocation(uv));
}
}
@jasonphillips
Copy link
Author

Preview

img_0173

Usage

Drop this file into the Sys/Shaders folder in your Dolphin installation (on OSX, you'll have to view package contents on Dolphin.app and look inside the Resources subfolder).

Select it as a Post-Processing Effect under the Enhancements tab in Graphics Config (while using Side-by-Side 3D mode).

image

Click Config for further options / fine tuning, which will let you adjust the image to fit your particular viewer.

image

Defaults are based on Google Cardboard on an iPhone 6S, using Duet Display to mirror Dolphin to the phone.

@jasonphillips
Copy link
Author

Please note that my code has now been merged into the official Dolphin project:
dolphin-emu/dolphin#4209

As of this moment, you'll have to download the latest development release here:
https://dolphin-emu.org/download/

The shader is now named lens_distortion in the Post-Processing dropdown.

@Air-max-fr
Copy link

Hello,
I have a problem with this shader.
When initializing a game at startup, I get a error :
error C1503 undefined variable "layer"

I note that this refers to line 56 :
"if (layer == 1)"
But this variable is never defined higher in the code...how to fix this?
I read that your shader is now integrated in Dophin under the name lens_distortion.glsl ...but the shader codes are strictly identical, and the result is unfortunately also strictly identical.... C1503 error :/

Thanks in advance for your answer, I really want to test your shader ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment