【发布时间】:2017-01-27 18:23:10
【问题描述】:
我一直在努力制作一个小灯光着色器。 它完美地工作,我的意思是,光线会按预期消失,它是围绕我的角色移动的一个圆圈。 仅当不存在该调整大小事件时,它才可能是完美的。
当 SFML 调整窗口大小时,它会放大所有内容,但以一种奇怪的方式。它放大了所有除了着色器。 我尝试调整窗口大小(我喜欢调整像素图形游戏的大小,我觉得它最漂亮。所以我不想阻止调整大小事件)。
这是我的着色器:
uniform vec3 light;
void main(void) {
float distance = sqrt(pow(gl_FragCoord.x - light.x, 2) + pow(gl_FragCoord.y - light.y, 2));
float alpha = 1.;
if (distance <= light.z) {
alpha = (1.0 / light.z) * distance;
}
gl_FragColor = vec4(0., 0., 0., alpha);
}
所以,问题是,我的窗口显示为 1280 x 736(以适应 32x32 纹理),并且我有一个 1920 x 1080 显示器。当我放大窗口以适应 1920 x 1080(包括标题栏)时,整个东西都正确调整大小,一切都很好,但着色器现在是 1920x1080(减去标题栏)。所以着色器需要不同的坐标(应该在 x = 32, y = 0 中,对于着色器来说,在 x = 48 y = 0 中)。
所以我想知道,是否可以用整个窗口放大着色器?我应该使用事件或类似的东西吗?
感谢您的回答^^
编辑:这里有一些图片: 所以这是调整大小之前的光照着色器(它在所有地方都是黑暗的,但在播放器上,就像它应该的那样)。 然后我调整窗口大小,播放器不动,纹理适合整个窗口,但灯光移动了。
所以,正确地解释一下,当我调整窗口大小时,我希望一切都适合窗口,所以它充满了纹理,但是当我这样做时,给我的着色器的坐标是调整大小之前的坐标,如果我移动它就像我没有调整窗口大小一样移动,所以我的播放器再也不会有灯光了。
我不确定它是否更清楚,但我已经尽力了。
EDIT2:这是我调用着色器的代码:
void Graphics::UpdateLight() {
short radius = 65; // 265 on the pictures
int x = m_game->GetPlayer()->GetSprite()->getPosition().x + CASE_LEN / 2; // Setting on the middle of the player sprite (CASE_LEN is a const which contains the size of a case (here 32))
int y = HEIGHT - (m_game->GetPlayer()->GetSprite()->getPosition().y + CASE_LEN / 2); // (the "HEIGHT -" part was set because it seems that y = 0 is on the bottom of the texture for GLSL)
sf::Vector3f shaderLight;
shaderLight.x = x;
shaderLight.y = y;
shaderLight.z = radius;
m_lightShader.setParameter("light", shaderLight);
}
【问题讨论】:
-
我发现您的解释难以理解。但是,很明显它不能很好地缩放,因为您使用的是窗口坐标 (gl_FragCoord) 而不是标准化的设备坐标或其他类型的不依赖于窗口分辨率的坐标。您可以从顶点着色器中获取 NDC 或将 gl_FragCoord 除以窗口分辨率(从统一变量中获取)
-
你不明白哪一部分?我可以试着澄清一下^^'好吧,我不使用顶点着色器,我只使用片段着色器(我对 glsl 很新,对不起:c)
-
我不太清楚你要做什么,这是像素艺术吗?你能提供一张图片吗?究竟要如何处理不同的窗口分辨率? 1024x1024 的窗口应该看起来与 512x512 的窗口完全一样吗?还是应该是它的 1/4 部分?
-
您应该向我们展示更多代码(例如,您在 C++ 中绘制的位置)。这听起来有点像您绘制事物的方式或窗口视图的设置方式存在问题。
-
@dv1729 我编辑了帖子以使其更清晰。马里奥,我的代码只是在屏幕上绘制精灵,没有什么特别的,唯一的问题是我不处理调整大小的事件,所以 SFML 单独完成这项工作,但没有告诉着色器窗口调整大小。跨度>