帮助在Android OpenGL 2.0中使用QCAR修正线条缩放问题

4
我正在使用 QCAR AR SDK 在 Android 上开发应用,它使用 OpenGL 2.0,而我对 2.0 还很新。QCAR SDK 用于基于 CV 的 AR 应用程序,并利用 OpenGL 将图形渲染到图像上。
我只想在屏幕中心画一个小的 X,使用以下代码。但是无论我将顶点赋予什么值,X 都会延伸到屏幕边缘,而不是正确的坐标位置。我无法确定这是否是缩放问题或我正在使用的坐标系统存在混淆。
你有任何想法关于为什么这些线条没有被正确地绘制吗?- 我知道在 1.1 中会更容易,但我必须使用 2.0。
谢谢
// 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();
}

有什么想法导致这种情况发生?


你还在关注这个问题吗?还是你自己解决了并放弃了这个问题?如果是前者,如果有任何不清楚之处,请随时问。如果是后者,那么放弃一个问题是不好的做法。如果解决方案完全不同于已给出的答案,请自由提供和接受您自己的答案。 - Christian Rau
1个回答

0
在你的顶点着色器中,你只是将顶点位置传递给光栅化器,而没有通过模型视图或投影矩阵对它们进行变换。虽然这是完全有效的,但你仍然必须关心你的坐标范围。
在顶点处理阶段之后,你的坐标必须在[-1,1]立方体中,超出此范围的一切都会被裁剪掉,然后该立方体会通过视口变换转换为屏幕空间,例如[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)

还要记住,默认情况下OpenGL中的y轴从底部到顶部。因此,如果您希望其行为有所不同(许多图像处理框架都是如此),则还必须在顶点着色器中否定y坐标(并在其他项目中交换glOrtho调用中的第3个和第4个值)。但请记住,如果有任何三角形渲染,这将颠倒它们的方向。

例如,在您的顶点着色器中只需执行以下操作:

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轴从底部到顶部。如果这不是您想要的,请随意尝试进行转换(还可以通过在CPU上预计算2.0 / screenSize 进行优化)。但始终记住,在顶点着色器之后,屏幕空间实际上是 [-1,1] - 立方体,然后通过视口变换(无论您为 glViewport 设置了哪些值)将其转换为实际的像素屏幕空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接