我试图将正投影投影矩阵加载到着色器中,但是当我运行代码并在窗口中单击时,最终所有点都指向(0,0,0), m的猜测是由于从未设置统一矩阵而导致的,因此所有内容都被乘以0。为此,我使用了Qt,OpenGL和GLM。任何想法为什么会这样?
我已经对其进行了一些调试,在将矩阵加载到resizeGL和initializeGL中的着色器中时似乎出现了问题,虽然不确定原因。
谢谢!
我的类处理所有OpenGL内容:
GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent), outline(false), drawMode(0) {
num_pts = 0;
drawMode = GL_POINTS;
next = 1;
ortho = glm::ortho(0.0f, 640.0f, 480.0f, 0.0f);
}
GLWidget::~GLWidget() {
}
void GLWidget::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_C:
cout << "Cleared all the points." << endl;
num_pts = 0;
pts.clear();
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
break;
case Qt::Key_W:
outline = !outline;
if (outline) {
cout << "Displaying outlines." << endl;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else {
cout << "Displaying filled polygons." << endl;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
break;
case Qt::Key_Space:
switch (next) {
case(0):
drawMode = GL_POINTS;
cout << "drawMode is GL_POINTS" << endl;
next = 1;
break;
case(1):
drawMode = GL_LINES;
cout << "drawMode is GL_LINES" << endl;
next = 2;
break;
case(2):
drawMode = GL_LINE_STRIP;
cout << "drawMode is GL_LINE_STRIP" << endl;
next = 3;
break;
case(3):
drawMode = GL_LINE_LOOP;
cout << "drawMode is GL_LINE_LOOP" << endl;
next = 4;
break;
case(4):
drawMode = GL_TRIANGLES;
cout << "drawMode is GL_TRIANGLES" << endl;
next = 5;
break;
case(5):
drawMode = GL_TRIANGLE_STRIP;
cout << "drawMode is GL_TRIANGLE_STRIP" << endl;
next = 6;
break;
case(6):
drawMode = GL_TRIANGLE_FAN;
cout << "drawMode is GL_TRIANGLE_FAN" << endl;
next = 0;
break;
}
break;
case Qt::Key_P:
cout << "Projection Location: " << projectionMatrixLoc << endl << endl;
cout << "Projection Matrix:" << endl << endl;
cout << "------------" << endl;
cout << ortho[0][0] << " ";
cout << ortho[1][0] << " ";
cout << ortho[2][0] << " ";
cout << ortho[3][0] << endl;
cout << "------------" << endl;
cout << ortho[0][1] << " ";
cout << ortho[1][1] << " ";
cout << ortho[2][1] << " ";
cout << ortho[3][1] << endl;
cout << "------------" << endl;
cout << ortho[0][2] << " ";
cout << ortho[1][2] << " ";
cout << ortho[2][2] << " ";
cout << ortho[3][2] << endl;
cout << "------------" << endl;
cout << ortho[0][3] << " ";
cout << ortho[1][3] << " ";
cout << ortho[2][3] << " ";
cout << ortho[3][3] << endl;
cout << "------------" << endl << endl << endl;
break;
}
update();
}
void GLWidget::mousePressEvent(QMouseEvent *event) {
glm::vec2 temp = glm::vec2(0.0);
temp.x = event->x();
temp.y = event->y();
pts.push_back(temp);
cout << "Added point (" << pts.back().x << ", " << pts.back().y << ") " << endl;
cout << "Number of points: " << pts.size() << endl;
num_pts++;
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, pts.size(), &pts, GL_DYNAMIC_DRAW);
update();
}
void GLWidget::initializeGL() {
initializeOpenGLFunctions();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glPointSize(4.0f);
// Create a new Vertex Array Object on the GPU which
// saves the attribute layout of our vertices.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a buffer on the GPU for position data
glGenBuffers(1, &positionBuffer);
// Upload the position data to the GPU, storing
// it in the buffer we just allocated.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
// Load our vertex and fragment shaders into a program object
// on the GPU
program = loadShaders(":/vert.glsl", ":/frag.glsl");
// Bind the attribute "position" (defined in our vertex shader)
// to the currently bound buffer object, which contains our
// position data for a single triangle. This information
// is stored in our vertex array object.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
GLint positionIndex = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);
glUseProgram(program);
projectionMatrixLoc = glGetUniformLocation(program, "ProjectionMatrix");
glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}
void GLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
ortho = glm::ortho(0.0f, (float)w, (float)h, 0.0f);
glUseProgram(program);
// problem area?
glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
// draw primitives based on the current draw mode
glDrawArrays(drawMode, 0, num_pts);
// draw points so we can always see them
// glPointSize adjusts the size of point
// primitives
glDrawArrays(GL_POINTS, 0, num_pts);
}
// Copied from LoadShaders.cpp in the the oglpg-8th-edition.zip
// file provided by the OpenGL Programming Guide, 8th edition.
const GLchar* GLWidget::readShader(const char* filename) {
#ifdef WIN32
FILE* infile;
fopen_s(&infile, filename, "rb");
#else
FILE* infile = fopen(filename, "rb");
#endif // WIN32
if (!infile) {
#ifdef _DEBUG
std::cerr << "Unable to open file '" << filename << "'" << std::endl;
#endif /* DEBUG */
return NULL;
}
fseek(infile, 0, SEEK_END);
int len = ftell(infile);
fseek(infile, 0, SEEK_SET);
GLchar* source = new GLchar[len + 1];
fread(source, 1, len, infile);
fclose(infile);
source[len] = 0;
return const_cast<const GLchar*>(source);
}
GLuint GLWidget::loadShaders(const char* vertf, const char* fragf) {
GLuint program = glCreateProgram();
// read vertex shader from Qt resource file
QFile vertFile(vertf);
vertFile.open(QFile::ReadOnly | QFile::Text);
QString vertString;
QTextStream vertStream(&vertFile);
vertString.append(vertStream.readAll());
std::string vertSTLString = vertString.toStdString();
const GLchar* vertSource = vertSTLString.c_str();
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &vertSource, NULL);
glCompileShader(vertShader);
{
GLint compiled;
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei len;
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetShaderInfoLog(vertShader, len, &len, log);
std::cout << "Shader compilation failed: " << log << std::endl;
delete[] log;
}
}
glAttachShader(program, vertShader);
// read fragment shader from Qt resource file
QFile fragFile(fragf);
fragFile.open(QFile::ReadOnly | QFile::Text);
QString fragString;
QTextStream fragStream(&fragFile);
fragString.append(fragStream.readAll());
std::string fragSTLString = fragString.toStdString();
const GLchar* fragSource = fragSTLString.c_str();
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragSource, NULL);
glCompileShader(fragShader);
{
GLint compiled;
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei len;
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetShaderInfoLog(fragShader, len, &len, log);
std::cerr << "Shader compilation failed: " << log << std::endl;
delete[] log;
}
}
glAttachShader(program, fragShader);
glLinkProgram(program);
{
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLsizei len;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetProgramInfoLog(program, len, &len, log);
std::cout << "Shader linker failed: " << log << std::endl;
delete[] log;
}
}
return program;
}
头文件:
#ifndef __GLWIDGET__INCLUDE__
#define __GLWIDGET__INCLUDE__
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QMouseEvent>
#include <glm/glm.hpp>
#include <vector>
// glm by default uses degrees, but that functionality
// is deprecated so GLM_FORCE_RADIANS turns off some
// glm warnings
#define GLM_FORCE_RADIANS
using glm::vec2;
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void mousePressEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
private:
GLuint loadShaders(const char* vertf, const char* fragf);
static const GLchar* readShader(const char* filename);
GLuint vao;
GLuint program;
GLuint positionBuffer;
GLint projectionMatrixLoc;
bool outline;
GLenum drawMode;
glm::mat4 ortho;
int next;
std::vector<vec2> pts;
int num_pts;
};
#endif
我的顶点着色器:
#version 330
in vec2 position;
uniform mat4 ProjectionMatrix;
void main() {
gl_Position = vec4(position.x, position.y, 0, 1)*ProjectionMatrix;
}
我的片段着色器:
#version 330
out vec4 color_out;
void main() {
color_out = vec4(1.0,1.0,1.0,1.0);
}