문제

I am interested in creating a shader effect similar to that of the game (don't shoot me for using this example) Animal Crossing. As you move forward and backward along the terrain, the world "curves" giving the sense of being on a round surface. The thing is, I want to apply this kind of effect to a 2D side-scroller.

Imagine a game like Terraria where both ends of the screen (left and right sides) are slightly bent downward to give the illusion of curvature.

I have tried to find an article explaining how to achieve such an effect, but I haven't much in the way of helpful direction pointing. I know this isn't the most organized or well-put question, but any help would be appreciated.

도움이 되었습니까?

해결책

Although I am not a fan of answering my own questions, I think I have found a way to achieve this effect and would like to share. By setting up a basic vertex shader, I was able to manipulate the location of the vertex along the y-axis depending on how far away it was from the center of the screen (the origin in my case). I originally used a linear absolute value equation to see how it worked, and I got something like this: enter image description here This is obviously a strange effect, but it is getting very close to what I want to achieve. I figured I would also try leveling the effect out by dividing the absolute value of the vertices' distance from the origin by some scalar. I started with 32 and the result was much more reasonable: enter image description here

As you can see, there is only a slight bend in the terrain.

This is all nice and all, but it isn't a "curve" yet. It is just an upside down 'V' with a bit of squashing done. So from here, it was easy to apply a nice curve by using a parabola and just flattening it out in the same fashion. The result was this: enter image description here The result was a very nice curve that I could modify to be any intensity I wanted. I also tried applying the graph of a 3rd degree equation, but it gave more of a try-hard 3D feel. I suppose I could apply the graph of a circle so I can accurately get the proper curve when I am on a planet with a specified radius, but I am satisfied for now.

The code turned out to be only a few lines long. Here is the GLSL code for the vertex shader:

#version 150

varying vec4 vertColor; //Just to send the color data to the fragment shader

uniform float tx; //Passed by the Java program to ensure the terrain curvature 
                  //is sinked by with player's movement, this value is usually 
                  //in the "lookThroughCamera" method where you handle the game 
                  //world's translation when the player moves

void main(void) {
    float v0 = gl_Vertex[1] - pow((gl_Vertex[0] + tx) / 64, 2); //this will be the new y-value for the vertex. 
                                                                   //It takes the original y-value and subtracts 
                                                                   //the absolute value of the x-value plus the offset 
                                                                   //on the x-axis of the player divided by 64 all to 
                                                                   //the power of 2. The division by 64 levels the 
                                                                   //curve out enough so it looks acceptable

    vec4 pos = vec4(gl_Vertex[0], v0, gl_Vertex[2], gl_Vertex[3]); //create the new position with the changed y-value
    gl_Position = gl_ModelViewProjectionMatrix * pos; //multiply it by your projection and modelview matrices
    vertColor = gl_Color.argb; //more color stuff that has nothing to do with the rest
}

EDIT: This approach does have a serious issue though. All vertical lines will remain vertical due to the fact they are not shifted along the x-axis properly. This is shown by the following image: enter image description here This gives an extremely unnatural look, and I have yet to come up with a proper solution to this.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top