OpenGL: как сортировать точки в зависимости от расстояния до камеры?

У меня есть структура, состоящая из 100 000 сфер в качестве точечных спрайтов с использованием OpenGL. У меня есть проблема, когда я вращаю структуру на ее центральной оси.
Точечный спрайт отображается в порядке, в зависимости от их массива, то есть последние перекрывают первый созданный точечный спрайт, не заботясь о глубине в трехмерном пространстве.

Как я могу отсортировать и переставить в реальном времени порядок точечных спрайтов, чтобы всегда сохранять трехмерную перспективу? Я предполагаю, что идея состоит в том, чтобы прочитать положение камеры относительно частиц, а затем отсортировать массив, чтобы всегда сначала показывать более близкие частицы.
Можно ли исправить с помощью шейдеров?

Вот мой шейдер:
shader.frag

#version 120
uniform sampler2D tex;
varying vec4 inColor;
//uniform vec3 lightDir;

void main (void) {
gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * inColor;
}

шейдерный верт

#version 120
// define a few constants here, for faster rendering
attribute float particleRadius;
attribute vec4 myColor;
varying vec4 inColor;

void main(void)
{
vec4 eyeCoord = vec4(gl_ModelViewMatrix * gl_Vertex);
gl_Position = gl_ProjectionMatrix * eyeCoord;
float distance = length(eyeCoord);
float attenuation = 700.0 / distance;
gl_PointSize = particleRadius * attenuation;
//gl_PointSize = 1.0 / distance * SIZE;
//gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
inColor = myColor;
}

метод рисования:

void MyApp::draw(){
//gl::clear( ColorA( 0.0f, 0.0f, 0.0f, 0.0f ), true );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// SET MATRICES TO WINDOW
gl::setMatricesWindow( getWindowSize(), false );
gl::setViewport( getWindowBounds() );
gl::enableAlphaBlending();

gl::enable( GL_TEXTURE_2D );
gl::enable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) );

mShader.bind();
// store current OpenGL state
glPushAttrib( GL_POINT_BIT | GL_ENABLE_BIT );

// enable point sprites and initialize it
gl::enable( GL_POINT_SPRITE_ARB );
glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, -1.0f );
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.1f );
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 200.0f );

// allow vertex shader to change point size
gl::enable( GL_VERTEX_PROGRAM_POINT_SIZE );

GLint thisColor = mShader.getAttribLocation( "myColor" );
glEnableVertexAttribArray(thisColor);
glVertexAttribPointer(thisColor,4,GL_FLOAT,true,0,theColors);

GLint particleRadiusLocation = mShader.getAttribLocation( "particleRadius" );
glEnableVertexAttribArray(particleRadiusLocation);
glVertexAttribPointer(particleRadiusLocation, 1, GL_FLOAT, true, 0, mRadiuses);

glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, mPositions);

mTexture.enableAndBind();
glDrawArrays( GL_POINTS, 0, mNumParticles );
mTexture.unbind();

glDisableClientState(GL_VERTEX_ARRAY);
glDisableVertexAttribArrayARB(thisColor);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableVertexAttribArrayARB(particleRadiusLocation);
// unbind shader
mShader.unbind();

// restore OpenGL state
glPopAttrib();

}

2

Решение

У вас есть два разных случая смешивания в void MyApp::draw()

  1. добавка — (src + dst)

    • Заказ независимый
  2. альфа — (src * src.a + (dst * (1.0 - src.a))

    • порядок depdendent

Первая функция смешивания не вызовет проблем, которые вы обсуждаете, поэтому я предполагаю, что mRoom.isPowerOn() == false и что мы имеем дело с альфа-смешением.

Чтобы решить проблемы зависимости порядка в последнем случае, вам нужно преобразовать ваши точки в пространство глаз и отсортировать их z координаты. Проблема здесь в том, что это не то, что может быть легко решено в GLSL — вам нужно отсортировать данные до Ваш вершинный шейдер работает (поэтому самый простой подход заключается в том, чтобы делать это на процессоре). Решения на основе графических процессоров возможны и могут быть необходимы для выполнения этого в режиме реального времени, учитывая огромное количество задействованных точек данных, но вы должны начать с выполнения этого на процессоре и выяснить, куда идти дальше.

При реализации сортировки помните, что точечные спрайты всегда выровнены по экрану z значение в пространстве глаза), поэтому вам не нужно беспокоиться о пересечении (точечный спрайт будет либо полностью перед, позади, либо параллельным любой другой точке спрайта, он перекрывается). Это делает их сортировку намного проще, чем другие типы геометрии, которые, возможно, придется разделить в точках пересечения и нарисовать дважды для правильного упорядочения.

3

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector