我试图让一个基本的 OpenGL 程序正常工作。我创建了两种方法来创建模型视图矩阵(目前非常初级,它只在 Z 轴上移动我的对象)和投影矩阵。
我的问题是,据我了解 OpenGL,我的投影矩阵应该将具有正 Z 坐标的顶点放置在屏幕上,而将具有负坐标的顶点放置在屏幕后面。
但我的经验是,如果我想要显示它,我需要将我绘制的立方体移动到负 z 方向。你能解释一下,这是为什么吗?我哪里错了?还是我的代码有错误?
我使用这个函数来创建我的投影矩阵:
void Perspective(float *a, float fov, float aspect, float zNear, float zFar)
{
for(int i = 0; i < 16; i++)
a[i] = 0.0f;
float f = 1.0f/float(tan(fov / 2.0f * (M_PI / 180.0f)));
a[0 + 4 * 0] = f / aspect;
a[1 + 4 * 1] = f;
a[2 + 4 * 2] = (zNear + zFar) / (zNear - zFar);
a[2 + 4 * 3] = 2.0f * zNear *+ zFar / (zNear - zFar);
a[3 + 4 * 2] = -1.0f;
}
而这个模型视图(我传递不同的偏移量,它们在 0 左右摆动,z 在 -2 左右摆动):
void Modelview(float *mv, float scale, float xOff, float yOff, float zOff)
{
for(int i = 0; i < 16; i++)
mv[i] = 0.0f;
mv[0 + 4 * 0] = scale;
mv[0 + 4 * 3] = xOff;
mv[1 + 4 * 1] = scale;
mv[1 + 4 * 3] = yOff;
mv[2 + 4 * 2] = scale;
mv[2 + 4 * 3] = zOff;
mv[3 + 4 * 3] = 1.0f;
}
矩阵都正确传递给opengl,我通过以下方式计算顶点位置:
gl_Position = modelview * projection * vertex_position;
这是整个代码,以防有人需要它:
主文件
#include <stdio.h>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <GL/glew.h>
#include <GL/glut.h>
#include "util.h"
GLuint positionBufferObject, program;
GLint projectionLoc, modelviewLoc, vertexLoc, colorLoc;
float zNear = 0.1f, zFar = 100.0f;
float projection[16], modelview[16];
const Vertex vertices[] =
{
Vertex(
Vector4f(0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
Vertex(
Vector4f(-1.0f, 0, -1.0f, 1.0f),
ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(0.0f, 1.0, -1.0f, 1.0f),
ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
Vertex(
Vector4f(1.0f, 0, -1.0f, 1.0f),
ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f))
};
const float vertexData[] =
{
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.366f, 0.0f, 1.0f,
-0.5f, -0.366f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
std::string strVertexShader = "simple.vert";
std::string strFragmentShader = "simple.frag";
void init();
void display();
void resize(int w, int h);
void InitializeProgram();
void InitializeVertexBuffer();
void InitializeGlutCallbacks();
void Perspective(float *a, float fov, float aspect, float zNear, float zFar);
void Modelview(float *mv, float scale, float xOff, float yOff, float zOff);
void ComputePositionOffsets(float &fXOffset, float &fYOffset, float &fZOffset, float &scale);
void PrintMat4(float *mat);
主文件
#include "main.h"
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("Test");
GLenum res = glewInit();
if(res != GLEW_OK)
{
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return -1;
}
init();
glutMainLoop();
return 0;
}
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float fXOffset = 0.0f, fYOffset = 0.0f, fZOffset = 0.0f, scale = 0.0f;
ComputePositionOffsets(fXOffset, fYOffset, fZOffset, scale);
Modelview(modelview, scale, fXOffset, fYOffset, -2.0f + fZOffset);
glUseProgram(program);
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, &projection[0]);
glUniformMatrix4fv(modelviewLoc, 1, GL_FALSE, &modelview[0]);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glEnableVertexAttribArray(vertexLoc);
glEnableVertexAttribArray(colorLoc);
glVertexAttribPointer(vertexLoc, sizeof(Vector4f)/sizeof(float), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glVertexAttribPointer(colorLoc, sizeof(ColorRGBA)/sizeof(float), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(Vertex)/2));
glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices)/sizeof(Vertex));
glDisableVertexAttribArray(vertexLoc);
glDisableVertexAttribArray(colorLoc);
glUseProgram(0);
glutSwapBuffers();
glutPostRedisplay();
}
void resize(int w, int h)
{
glViewport(0, 0, w, h);
Perspective(projection, 90.0f, float(w)/float(h), zNear, zFar);
PrintMat4(projection);
}
void InitializeProgram()
{
std::vector<GLuint> shaderList;
shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));
program = CreateProgram(shaderList);
vertexLoc = glGetAttribLocation(program, "vertex_position");
colorLoc = glGetAttribLocation(program, "vertex_color");
modelviewLoc = glGetUniformLocation(program, "modelview");
projectionLoc = glGetUniformLocation(program, "projection");
std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
void InitializeVertexBuffer()
{
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void InitializeGlutCallbacks()
{
glutDisplayFunc(display);
glutReshapeFunc(resize);
}
void init()
{
InitializeProgram();
InitializeVertexBuffer();
InitializeGlutCallbacks();
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glEnable(GL_DEPTH_TEST);
}
void Perspective(float *a, float fov, float aspect, float zNear, float zFar)
{
for(int i = 0; i < 16; i++)
a[i] = 0.0f;
float f = 1.0f/float(tan(fov / 2.0f * (M_PI / 180.0f)));
a[0 + 4 * 0] = f / aspect;
a[1 + 4 * 1] = f;
a[2 + 4 * 2] = (zNear + zFar) / (zNear - zFar);
a[2 + 4 * 3] = 2.0f * zNear *+ zFar / (zNear - zFar);
a[3 + 4 * 2] = -1.0f;
}
void Modelview(float *mv, float scale, float xOff, float yOff, float zOff)
{
for(int i = 0; i < 16; i++)
mv[i] = 0.0f;
mv[0 + 4 * 0] = scale;
mv[0 + 4 * 3] = xOff;
mv[1 + 4 * 1] = scale;
mv[1 + 4 * 3] = yOff;
mv[2 + 4 * 2] = scale;
mv[2 + 4 * 3] = zOff;
mv[3 + 4 * 3] = 1.0f;
}
void ComputePositionOffsets(float &fXOffset, float &fYOffset, float &fZOffset, float &scale)
{
float elapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
float timeScale = 3.14159f * 2.0f;
float xLoopDuration = 8.0f;
float yLoopDuration = 3.0f;
float zLoopDuration = 2.0f;
float scaleLoopDuration = 10.0f;
float xLoopProgress = fmodf(elapsedTime, xLoopDuration) / xLoopDuration;
float yLoopProgress = fmodf(elapsedTime, yLoopDuration) / yLoopDuration;
float zLoopProgress = fmodf(elapsedTime, zLoopDuration) / zLoopDuration;
float scaleLoopProgress = fmodf(elapsedTime, scaleLoopDuration) /scaleLoopDuration;
fXOffset = sinf(xLoopProgress * timeScale) * 0.5f;
fYOffset = sinf(yLoopProgress * timeScale) * 0.5f;
fZOffset = sinf(zLoopProgress * timeScale) * 0.5f;
scale = 1/(1 + sinf(scaleLoopProgress * timeScale) * 0.5f);
}
void PrintMat4(float *mat)
{
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
std::cout << mat[j * 4 + i] << "\t";
}
std::cout << std::endl;
}
std::cout << std::endl;
}