/* Shader for application of a spherical projection of textures during drawing. * * (C)2010-2011 by Ingmar Schneider and Mario Kleiner. * Licensed to you under MIT license. * * This is version 2, with improved math by Ingmar Schneider to fix the * problems with central magnification and anisotropy. * */ #extension GL_ARB_texture_rectangle : enable uniform int doFilter; uniform sampler2DRect Image; uniform vec2 inSize; uniform vec2 inOffset; uniform vec2 outSize; /* Width of the projection area at a distance R in cm */ uniform float Wflat; /* Radius of the used spherical screen in cm */ uniform float R; void main() { vec4 texcolor, tl, tr, bl, br; /* Get wanted output pixel coordinates for which we should remap: */ /* texoutpos is the location of the output pixel for which we need */ /* to compute the final remapped color value */ vec2 texoutpos = (gl_TexCoord[0].st) - vec2(0.5, 0.5); /* Apply 2D offset to output pixel location, as well as a 2D rescaling: */ /* This to account for situations where not the full display area of */ /* display device is used. */ texoutpos = clamp(texoutpos, vec2(0.0), outSize); /* Geometric remapping/warping: Recompute and assign modified components */ /* of texoutpos, based on texinpos and display geometry: */ float Wunits = Wflat / R; vec2 UnitsPerPixel = vec2(Wunits)/ outSize; /* Centering */ texoutpos = (texoutpos - ((outSize+1.0)/2.0)) * UnitsPerPixel; /* Unwarping */ texoutpos = texoutpos / sqrt(1.0 - pow(abs(texoutpos.x), 2.0) - pow(abs(texoutpos.y), 2.0)); /* Retransformation to image coordinates */ texoutpos = (texoutpos/UnitsPerPixel) + ((outSize+1.0)/2.0); /* Offsetting */ vec2 texinpos = inOffset + texoutpos; /* texinpos now contains the location of the final input image pixel to read */ /* for creation of the final output color pixel. This value may be fractional. */ /* Need to filter input image texture ourselves? */ if (doFilter > 0) { /* Need to do our own bilinear filtering: Get colors of four nearest */ /* neighbour texels for given non-integral, fractional 'texinpos': */ tl=texture2DRect(Image, floor(texinpos)); tr=texture2DRect(Image, floor(texinpos) + vec2(1.0, 0.0)); bl=texture2DRect(Image, floor(texinpos) + vec2(0.0, 1.0)); br=texture2DRect(Image, floor(texinpos) + vec2(1.0, 1.0)); /* Perform weighted linear interpolation -- bilinear interpolation of the 4: */ tl=mix(tl,tr,fract(texinpos.x)); bl=mix(bl,br,fract(texinpos.x)); texcolor = mix(tl, bl, fract(texinpos.y)); } else { /* Standard case: Hardware does bilinear filtering: */ texcolor = texture2DRect(Image, texinpos); } /* Set all undefined (outside input image) pixels to black background color. */ if (texinpos.x < 0.0 || texinpos.x >= inSize.x || texinpos.y < 0.0 || texinpos.y >= inSize.y || texinpos.x != texinpos.x || texinpos.y != texinpos.y) { gl_FragColor = vec4(0.0); } else { /* Multiply filtered texcolor with incoming fragment color (GL_MODULATE emulation): */ /* Assign result as output fragment color: */ gl_FragColor = texcolor * gl_Color; } }