Помогите исправить масштабирование линии в Android OpenGL 2.0 с QCAR - PullRequest
4 голосов
/ 02 августа 2011

Я работаю с QCAR AR SDK в Android, который использует OpenGL 2.0, и я новичок в 2.0. QCAR SDK предназначен для приложений на основе CV и использует OpenGL для рендеринга изображений.

Я просто хотел бы нарисовать маленький X в центре экрана, и я использую следующий код. Но вместо того, чтобы нарисовать X с правильными координатами, X простирается до краев экрана. Это происходит независимо от того, какие значения я назначаю вершинам. Я не могу понять, если это проблема масштабирования или какая-то путаница в системе координат, которую я использую.

Есть идеи, почему эти линии не нарисованы должным образом? - Я знаю, что это было бы проще в 1.1, но я должен использовать 2.0.

Thnx

// Clear color and depth buffer 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);


    GLfloat diagVertices[12];

    diagVertices[0] = -10;
    diagVertices[1] = -10;
    diagVertices[2] = 0.0f;

    diagVertices[3] = 10;
    diagVertices[4] = 10;
    diagVertices[5] = 0.0f;

    diagVertices[6] = -10;
    diagVertices[7] = 10;
    diagVertices[8] = 0.0f;

    diagVertices[9] = 10;
    diagVertices[10] = -10;
    diagVertices[11] = 0.0f;

    glUseProgram(diagonalShaderProgramID);
// map the border vertices
    glVertexAttribPointer(diagVertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &diagVertices[0]);
// draw it
glEnableVertexAttribArray(diagVertexHandle);

glLineWidth(3.0f);
glDrawArrays(GL_LINES, 0, 4);
glDisableVertexAttribArray(diagVertexHandle);

Вот шейдер, который я использую ..

static const char* diagLineMeshVertexShader = " \
  \
attribute vec4 vertexPosition; \
 \
void main() \
{ \
   gl_Position = vertexPosition; \
} \
";

static const char* diagLineFragmentShader = " \
 \
precision mediump float; \
 \
void main() \
{ \
   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \
} \
";

Обновление:

Итак, я создал среду сборки в Windows 7 (64), используя Eclipse и Cygwin, и протестировал тот же подход - рисование массивов атрибутов вершин. Кодовая база получена из простого примера lighthouse3D, демонстрирующего GSLS. Я скомпилировал и запустил образец, чтобы подтвердить, что он рендерится как положено. Затем я реализовал массивы вершин, как указано выше. Я вижу точно такую ​​же проблему. Линии простираются до краев окна независимо от их значений вершин.

Это для GL_VERSION 2.1.2. Реализация массивов атрибутов вершин и метод их рендеринга, похоже, идентичны другим примерам, которые я нашел в справочных ресурсах.

Вот код .. - Я закомментировал разделы кода lighthouse3d, которые я изменил.

#define WIN32

#include <stdio.h>
#include <stdlib.h>

#include <GL/Glee.h>
#include <GL/glut.h>
#include "textfile.h"


GLuint v,f,f2,p;
float lpos[4] = {1,0.5,1,0};
GLfloat crossVertices[12];
GLint lineVertexHandle = 0;

void changeSize(int w, int h) {

// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
    h = 1;

float ratio = 1.0* w / h;

// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the correct perspective.
//gluPerspective(45,ratio,1,1000);
gluPerspective(45,ratio,1,10);
glMatrixMode(GL_MODELVIEW);


}


void renderScene(void) {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
          0.0,0.0,0.0,
          0.0f,1.0f,0.0f);

glLightfv(GL_LIGHT0, GL_POSITION, lpos);
//glutSolidTeapot(1);

// map the border vertices
glVertexAttribPointer(lineVertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &crossVertices[0]);
glEnableVertexAttribArray(lineVertexHandle);


glLineWidth(1.0f);
glDrawArrays(GL_LINES, 0, 4);
glDisableVertexAttribArray(lineVertexHandle);
glutSwapBuffers();


}

void processNormalKeys(unsigned char key, int x, int y) {

if (key == 27) 
    exit(0);
}


void setShaders() {

char *vs = NULL,*fs = NULL,*fs2 = NULL;

v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
f2 = glCreateShader(GL_FRAGMENT_SHADER);


vs = textFileRead("toon.vert");
fs = textFileRead("toon.frag");
fs2 = textFileRead("toon2.frag");

const char * ff = fs;
const char * ff2 = fs2;
const char * vv = vs;

glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
glShaderSource(f2, 1, &ff2,NULL);

free(vs);free(fs);

glCompileShader(v);
glCompileShader(f);
glCompileShader(f2);

p = glCreateProgram();
glAttachShader(p,f);
glAttachShader(p,f2);
glAttachShader(p,v);

glLinkProgram(p);
glUseProgram(p);
}

void defineVertices(){
crossVertices[0]=       10.0f;
crossVertices[1]=0.0f;
crossVertices[2]=0.0f;
crossVertices[3]=       -1 * 10.0f;
crossVertices[4]=0.0f;
crossVertices[5]=0.0f;
crossVertices[6]=0.0f;
crossVertices[7]=       10.0f;
crossVertices[8]=0.0f;
crossVertices[9]=0.0f;
crossVertices[10]=      -1 * 10.0f;
crossVertices[11]=0.0f;
}


int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("MM 2004-05");

glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);

glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
glEnable(GL_CULL_FACE);
    /*
glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
    printf("Ready for OpenGL 2.0\n");
else {
    printf("OpenGL 2.0 not supported\n");
    exit(1);
}
*/
setShaders();
defineVertices();

glutMainLoop();

// just for compatibiliy purposes
return 0;
}

а вот вершинный шейдер из примера lighthouse3D ...

varying vec3 normal, lightDir;

void main()
{   
lightDir = normalize(vec3(gl_LightSource[0].position));
normal = normalize(gl_NormalMatrix * gl_Normal);

gl_Position = ftransform();
}

Есть идеи, что может быть причиной этого?

1 Ответ

0 голосов
/ 03 сентября 2011

В своем вершинном шейдере вы просто передаете позиции вершин в растеризатор, не трансформируя их в виде модели или матрицу проекции.В то время как это совершенно верно, вам все равно нужно позаботиться о диапазоне, в котором находятся ваши координаты.

После этапа обработки вершин ваши координаты должны находиться в [-1,1] -кубе, все там отсекается иэтот куб затем преобразуется с помощью преобразования vieport в пространство экрана, например, [0,w]x[0,h]x[0,1].Таким образом, ваши координаты варьируются от -10 до 10, так что ваша линия на самом деле в 10 раз больше размера экрана.Если вы имеете в виду пиксели, вы должны масштабировать свои значения x, y от [-w/2,w/2]x[-h/2,h/2] до [-1,1] в вершинном шейдере.

Это та же проблема в предоставленном вами настольном проекте GL, которую вы называете ftransform в шейдере, но ваша матрица проекции - это простая перспективная матрица, которая не сильно уменьшает ваши координаты.Поэтому в этом проекте замените вызов на gluPerspective на glOrtho(-0.5*w, 0.5*w, -0.5*h, 0.5*h, -1.0, 1.0), если вы хотите, чтобы координаты линии были пикселями.

И помните, что по умолчанию y в OpenGL идет снизу вверх.Таким образом, если вы хотите, чтобы это велось по-другому (как это делают многие платформы обработки изображений), то вы должны также отрицать свою y-координату в вершинном шейдере (и аналогично поменять 3-е и 4-е значение в вызове glOrtho в другомпроект).Но имейте в виду, что это изменит ориентацию любых треугольников, которые вы визуализируете, если таковые имеются.

Так, например, в вашем вершинном шейдере просто сделайте что-то вроде:

uniform vec2 screenSize;           //contains the screen size in pixels
attribute vec2 vertexPosition;     //why take 4 if you only need 2?

void main()
{
    gl_Position = vec4(2.0*vertexPosition/screenSize, 0.0, 1.0);
}

Это даст вамсистема координат в пикселях с началом координат в центре и осью Y, идущей снизу вверх.Если это не то, что вам нужно, то не стесняйтесь поиграть с преобразованием (его также можно немного оптимизировать, предварительно вычислив 2.0/screenSize на процессоре).Но всегда имейте в виду, что после вершинного шейдера пространство экрана на самом деле является [-1,1] -кубом, и затем оно преобразуется в реальное пространство экрана в пикселях с помощью преобразования области просмотра (какие бы значения вы не указали glViewport).

...