我目前正在尝试创建一个游戏,您可以在LibGDX for Java中访问行星。要做到这一点,我使用TiledMap
,它基本上只是一个瓦片数组来代表行星本身。为了获得必要的曲率,我使用着色器;它的工作原理是为每个顶点指定一个角度并根据摄像机位置放置它。它看起来像这样:
片段:
precision highp float;
varying vec2 uv;
varying vec4 v_color;
uniform sampler2D u_texture;
void main() {
vec4 color = texture2D(u_texture, uv) * v_color;
gl_FragColor = color;
}
顶点:
attribute vec4 a_color;
attribute vec3 a_position;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
uniform float WORLD_WIDTH;
uniform float CAM_X;
varying vec2 uv;
varying vec4 v_color;
const float PI = 3.14159265;
void main() {
uv = a_texCoord0;
v_color = a_color;
float radius = a_position.y;
float angle = 2.0 * PI * ((a_position.x-CAM_X)/ WORLD_WIDTH);
float camAngle = 2.0 * PI * (CAM_X / WORLD_WIDTH);
vec3 newPos = vec3(a_position);
newPos.x = CAM_X + cos(-angle + 0.5 * PI) * radius ;
newPos.y = sin(-angle + 0.5 * PI) * radius;
gl_Position = u_projTrans * vec4(newPos, 1.0);
}
在没有任何其他内容的情况下应用此着色器如下所示:
我现在使用阴影贴图来照亮游戏。这是通过在纹理上绘制灰色阴影并在此之后在游戏玩法上拉伸纹理(特别是FrameBuffer
)来完成的。没有任何着色器,它看起来像这样:
如果我现在不仅将着色器应用于平铺,而且还应用于阴影贴图,我会得到一个扭曲的阴影贴图:
我相信这是由于着色器使用顶点来实现曲率。阴影贴图只有四个顶点,实际上不能拉伸以实现曲率,而地图中的每个贴图都有四个顶点,这样可以产生很好的效果。我目前还不知道,曲率效果如何仍然可以实现,所以如果你有想法或其他一些建议让我知道,你不一定要发布任何代码,只是一般方法也会很好。
编辑:我现在尝试使用片段着色器:
这是我尝试用来渲染阴影贴图的片段着色器,结果是this。你可以看到它有一个基本的圆形形式,但有点扭曲(我知道问题出现的角度如何使用,但我不知道如何解决它)。这是在着色器中使用uv表示纹理的方式:http://i.imgur.com/pTQp8AJ.png
precision highp float;
uniform sampler2D u_texture;
uniform float TEXTURE_WIDTH;
uniform float TEXTURE_HEIGHT;
uniform float VIEWPORT_WIDTH;
uniform float VIEWPORT_HEIGHT;
uniform float CAM_X;
uniform float CAM_Y;
varying vec2 uv;
varying vec4 v_color;
void main() {
// THE RATIO OF TEXTURE WIDTH TO TEXTURE_HEIGHT WHICH YOU MULTIPLY WITH UV.X TO NOT ALLOW STRETCHING
// (LOOK AT HOW THE TEXTURE IS REPRESENTED TO UNDERSTAND)
float k = TEXTURE_WIDTH / TEXTURE_HEIGHT;
uv.x *= k;
// THE CENTER OF THE PLANET RELATIVE TO TEXTURE_HEIGHT AS 1
vec2 m;
m.x = (k * VIEWPORT_WIDTH) / (2.0 * TEXTURE_WIDTH);
m.y = - ((CAM_Y - 0.5 * VIEWPORT_HEIGHT) / TEXTURE_HEIGHT);
// THE DISTANCE FROM CURRENT UV COORDINATE TO CENTER
float d = distance(uv, m);
// THE RANGE OF ANGLES
float a = abs(atan(m.x/m.y)) * 2.0;
// THE ANGLE OF THE CURRENT UV COORDINATE
// + THE LEFTOFER ANGLE FROM HOW MUCH THE PLAYER HAS MOVED FROM THE CLOSEST INTEGER POSITION
float angle = atan((uv.x - m.x)/(uv.y - m.y)) + (CAM_X - floor(CAM_X)) * (a / VIEWPORT_WIDTH);
// ASIGN THE DISTANCE AND ANGLE TO ONE POINT IN THE TEXTURE
uv.x = ((angle + 0.5 * a) / a)*(VIEWPORT_WIDTH / TEXTURE_WIDTH);
uv.y = d + m.y;
// GET THE COLOR OF THE TEXTURE AT THIS POINT
vec4 color = texture2D(u_texture, uv) * v_color;
gl_FragColor = color;
}