Я пишу клон Wolfenstein 3D, используя только ядро OpenGL 3.3 для университета, и я столкнулся с небольшой проблемой со спрайтами, а именно с их правильным масштабированием в зависимости от расстояния.
Насколько я могу судить, предыдущие версии OGL действительно делали это за вас, но эта функциональность была удалена, и все мои попытки реализовать ее заново привели к полному провалу.
Моя текущая реализация проходима на дистанциях, не слишком плохая на средних и причудливая на близких.
Основная проблема (я думаю) в том, что я не понимаю математику, которую использую.
Целевой размер спрайта немного больше, чем область просмотра, поэтому он должен «выходить из поля зрения», когда вы подходите к нему, но это не так. Он становится меньше, и это меня сильно сбивает с толку.
Я записал небольшое видео об этом, на случай, если слов недостаточно. (Моя справа)
Может ли кто-нибудь указать мне, где я ошибаюсь, и объяснить, почему?
Код:
C ++
// setup
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
glEnable(GL_PROGRAM_POINT_SIZE);
// Drawing
glUseProgram(StaticsProg);
glBindVertexArray(statixVAO);
glUniformMatrix4fv(uStatixMVP, 1, GL_FALSE, glm::value_ptr(MVP));
glDrawArrays(GL_POINTS, 0, iNumSprites);
Vertex Shader
#version 330 core
layout(location = 0) in vec2 pos;
layout(location = 1) in int spriteNum_;
flat out int spriteNum;
uniform mat4 MVP;
const float constAtten = 0.9;
const float linearAtten = 0.6;
const float quadAtten = 0.001;
void main() {
spriteNum = spriteNum_;
gl_Position = MVP * vec4(pos.x + 1, pos.y, 0.5, 1); // Note: I have fiddled the MVP so that z is height rather than depth, since this is how I learned my vectors.
float dist = distance(gl_Position, vec4(0,0,0,1));
float attn = constAtten / ((1 + linearAtten * dist) * (1 + quadAtten * dist * dist));
gl_PointSize = 768.0 * attn;
}
Fragment Shader
#version 330 core
flat in int spriteNum;
out vec4 color;
uniform sampler2DArray Sprites;
void main() {
color = texture(Sprites, vec3(gl_PointCoord.s, gl_PointCoord.t, spriteNum));
if (color.a < 0.2)
discard;
}