Created
June 25, 2016 08:40
-
-
Save 4aiman/9574a8189b32e7c2fa42f35156746ad1 to your computer and use it in GitHub Desktop.
Revisions
-
Doruk Turak revised this gist
Jun 24, 2016 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -109,4 +109,7 @@ We also divide the multiplied xb*f with aspect ratio here to get the square back Lastly, our coordinates are in [0,2] space (ignoring x's division by aspect ratio, it is still higher than 1 anyway) so we divide the uv by 2 just before we se it in Texel. The rest is what you wanna make of it. Try and see the result! I'd be glad if someone did and posted a gif because I don't know how to. Sources: - http://www.geeks3d.com/20130705/shader-library-circle-disc-fake-sphere-in-glsl-opengl-glslhacker/4/ -
Doruk Turak created this gist
Jun 24, 2016 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,112 @@ # Fake 2D Sphere effect Wanna have a rotating planet? Prerequisites: - Shaders - Trigonometry - Magic ### Lua On our lua side, you will need to load an image (ofc), a shader, make a mesh and do some other things. You don't need a mesh if your image is square, but for others, we need to tweak texture coordinates and I don't know a better way, so. I guess it is redundant to say your image should be seamless on the edge it is rotating. My image is this:  **In love.load:** ```lua earthimg = love.graphics.newImage("res/PathfinderMap.jpg") -- load the image earthimg:setWrap("repeat", "repeat") local earthimgw, earthimgh = earthimg:getDimensions() earthImageAspectRatio = earthimgw / earthimgh ``` We are going to use the aspect ratio to map the rectangle on the sphere properly. Like so: ```lua local vertices = { {0,0, 0,0, 255,255,255}, --topleft {500,0, 0 + 1/eia,0, 255,255,255}, --topright {500,500, 0 + 1/eia,1, 255,255,255}, --bottomright {0,500, 0,1, 255,255,255} --bottomleft } earth = love.graphics.newMesh(vertices) earth:setTexture(earthimg) time = 0 ``` (Tabs and spaces might be mixed there. I don't care, don't copy paste) You should know that texture coordinates are between 0 and 1, so to pick a square area off of our image we have to do that. If your image is already square then you can directly draw the image I suppose. **In love.update:** ```lua t = t + dt ``` **In love.draw:** ```lua love.graphics.setShader(earthShader) earthShader:send("time", t) earthShader:send("imageAspectRatio", earthImageAspectRatio) love.graphics.draw(earth, 0, 0, 0, 1, 1, 0, 0) ``` That time is going to be used to rotate. Load the shader on your own, there are various ways you can go with that. I use a utility function to load from an external file so I didn't put that here. Aspect ratio is going to be used again to fix square-rectangle stuff. Now that we are done here, let's move on to the shader. ### Shader You don't need to modify the vertex shader, all of the magic happens in the vertex. First the declarations: ```glsl extern number time; extern number imageAspectRatio; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ //Init vec4 pixel; ``` We are gonna need to forward declare a vec4, that I named "pixel" here. This is gonna be our color result. The main part: ```glsl //Fake Sphere number xb = 2.0 * (texture_coords.x * imageAspectRatio - 0.5); number yb = 2.0 * (texture_coords.y - 0.5); number r = sqrt(xb * xb + yb * yb); //value between 0 and sqrt(2) ``` Firt of all, we multiply our x coordinate with the aspect ratio to push it back to [0,1] space. We will need this for the algorith, and we will divide it back after the algorithm, to put it back to square-space. As we take the x and y coordinates, and subtract 0.5 from both, this shifts the coordinate space from [0,1] , [0,1] to [-0.5,-0.5] , [0.5,0.5]. And when we multiply by two, this expands to [-1,-1] , [1,1]. Why we do this is simple: We are going to put a unit circle in the middle of it. To test whether or not a point is in our unit circle, our coordinate space needs to be the same. The "r" here is the "length", the norm of our final texture_coords vector, and if its length isnt more than 1, so inside the unit cicle, we render it: ```glsl if(r>1.0) { pixel = vec4(0); } else { number f = (1.0-sqrt(1.0-r))/(r); vec2 uv; uv.x = (xb * f) /imageAspectRatio + time; uv.y = yb * f + 1; pixel = Texel(texture, uv / 2); pixel = pixel; } return pixel * color; } ``` What we do here with f is a little more complex. That is what makes our "fake sphere" effect. Plotting "(1.0-sqrt(1.0-r))/r" on [Wolfram Alpha](https://www.wolframalpha.com) describes it visually better than I can verbally: See that immediate increase nearing 1.0 on real values? As r nears 1.0, so the closer the pixel is to the edge, f is higher. Using f as a denominator there makes texture coordinates move slower near the centre and faster near the edges, simulating a fake tangented look for the edges, making it seem like a sphere. This is just one way to make it seem like a sphere, I'm sure there would be other ways. This particular math equation is chosen only for that falloff property and nothing else. As xb and yb are in [-1,-1] , [1,1] coordinate space, after we multiply them with f for the effect, we should move them back into [0,1] space before we use them as texture coordinates in Texel function. We add 1 to the y, moving it to [0,2] space, and normally we need to add 1 to x too but that isnt very important now, as x axis wrapping is seamless and we add "time" anyway. If your sphere isnt rotating around its x-axis you should add 1 here. We also divide the multiplied xb*f with aspect ratio here to get the square back. Theoretically, you can divide the x coordinate with aspect ratio anywhere after you multiplied it with f and added 1 to it. As we dont need to add 1 here, I chose to do that there. Lastly, our coordinates are in [0,2] space (ignoring x's division by aspect ratio, it is still higher than 1 anyway) so we divide the uv by 2 just before we se it in Texel. The rest is what you wanna make of it. Try and see the result! I'd be glad if someone did and posted a gif because I don't know how to.