2015-08-23 2 views
-1

У меня возникли проблемы с поиском расположения 2D-объекта в моей сцене с использованием экранных координат. На данный момент у меня есть что-то работающее (код ниже), но он хочет координаты NDC, с которыми работать нелегко. Я не могу понять, где это происходит. Я думаю, что я использовал все, как должно быть, поэтому я думаю, что что-то забыл.Преобразование OpenGL в координатах NDC вместо координат экрана (2D)

Вот код, который обрабатывает рисование объектов в моей сцене:

glClearDepth(1.0f); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 


// RENDERING HERE 
colorProgram.bind(); 

for (size_t t = 0; t < objectsWithGraphicsComponentInThisScene.size(); ++t) 
{ 
    // set texture 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, objectsWithGraphicsComponentInThisScene[t]->getComponent<GraphicsComponent>()->getTexture()); 

    GLint texLocation = colorProgram.getUniformLocation("texSampler"); 
    glUniform1i(texLocation, 0); 

    glm::mat4 trans; 
    trans = glm::translate(glm::mat4x4(1.0f), glm::vec3(objectsWithGraphicsComponentInThisScene[t]->getPosition().x, objectsWithGraphicsComponentInThisScene[t]->getPosition().y, 0)); 
    GLint transMatLocation = colorProgram.getUniformLocation("transformMatrix"); 
    glUniformMatrix4fv(transMatLocation, 1, GL_FALSE, glm::value_ptr(trans)); 

    // set camera Matrix 
    GLint projMatLocation = colorProgram.getUniformLocation("projectionMatrix"); 
    glm::mat4 cameraMatrix = camera->getCameraMatrix(); 
    glUniformMatrix4fv(projMatLocation, 1, GL_FALSE, glm::value_ptr(cameraMatrix)); 

    objectsWithGraphicsComponentInThisScene[t]->getComponent<GraphicsComponent>()->getSprite()->draw(); 

    // unbind all 
    glBindTexture(GL_TEXTURE_2D, 0); 
} 

colorProgram.unbind(); 

где colorProgram является шейдер мои спрайты использовать и getPosition() просто возвращает значение, которое я установил. (где значения x y и z должны быть указаны как координаты экрана). поэтому, например, getPosition может возвращать [100, 50, 0], но это отобразит объект за пределами экрана (экран 1280x720).

Теперь код, который делает спрайт (objectsWithGraphicsComponentInThisScene [т] -> GetComponent() -> getSprite() -> рисуем();):

void Sprite::draw() 
{ 
glBindBuffer(GL_ARRAY_BUFFER, vboID); 

glEnableVertexAttribArray(0); 

// position 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); 

//color 
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color)); 

// uv 
glVertexAttribPointer(2, 2, GL_FLOAT, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, uv)); 

glDrawArrays(GL_TRIANGLES, 0, 6); 

glDisableVertexAttribArray(0); 

glBindBuffer(GL_ARRAY_BUFFER, 0); 
} 

А вот код в шейдере (colorProgram): Vertex Shader:

#version 130 
// per vertex 

// input data from VBO 
in vec2 vertexPosition; 
in vec4 vertexColor; 
in vec2 vertexUV; 

// output to fragment shader 
out vec4 fragmentColor; 
out vec2 fragmentUV; 

uniform mat4 projectionMatrix; 
uniform mat4 transformMatrix; 

void main() 
{ 
mat4 resultMatrix = transformMatrix * projectionMatrix; 
gl_Position.xy = (resultMatrix * vec4(vertexPosition, 0.0, 1.0)).xy; 
gl_Position.z = 0.0; 

// Indicate that the coordinates are normalized 
gl_Position.w = 1.0; 

fragmentColor = vertexColor; 
fragmentUV = vec2(vertexUV.x, 1.0 - vertexUV.y); 
} 

пиксельный шейдер

#version 130 
// per pixel 

// input from vertex shader 
in vec4 fragmentColor; 
in vec2 fragmentUV; 

out vec4 color; 

uniform sampler2D texSampler; 

void main() 
{ 
vec4 textureColor = texture(texSampler, fragmentUV); 
if (textureColor.a < 0.5) discard; 
color = fragmentColor * textureColor; 
} 

I f вам нужно больше кода, я был бы счастлив добавить больше, хотя я думаю, что это все, что нужно.

+0

Попробуйте использовать матрицу орфографической проекции ([glm :: ortho] (http://glm.g-truc.net/0.9.2/api/a00245.html#ga71777a3b1d4fe1729cccf6eda05c8127)). – BDL

+0

Я установил это при создании моей камеры. мне нужно делать это каждый раз, когда я делаю призыв к розыгрышу? – Dries

+0

Вы должны положить его в форму шейдера. Как и любая другая матрица. Я бы умножал его на 'cameraMatrix', так как вы уже называете его' projectionMatrix' в шейдере;) – BDL

ответ

1

Эта последовательность в вашей вершинного шейдера

mat4 resultMatrix = transformMatrix * projectionMatrix; 
gl_Position.xy = (resultMatrix * vec4(vertexPosition, 0.0, 1.0)).xy; 

очень маловероятно, что вы на самом деле хотите. Так как вы используете матрицу * вектор соглашение, вы в конечном итоге с

position = transform * projection * v 
     = transform * (projection * v) 

Другими словами: вы применить преобразование после проекция. Поскольку после проецирования объем просмотра находится в диапазоне [-1,1]^3 (в евклидовом пространстве NDC после перседитивного деления. В действительности мы работаем в пространстве клипов здесь, где это [-w, w]^3, но в этом контексте это не очень важно), перевод объекта по значениям, равным 100 единицам, непременно выведет его из усечения.

Вы должны просто изменить порядок умножения матрицы.

+0

Вау, это, похоже, решило проблему! Большое спасибо! :) – Dries