基本的な OpenGL プログラムを動作させようとしています。モデルビュー マトリックスを作成する 2 つのメソッドを作成しました (現時点では非常に初歩的で、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;
}
そして、これはModelview用です(さまざまなオフセットを渡します。それらは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;
誰かが必要な場合に備えて、コード全体を次に示します。
main.h
#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);
main.cpp
#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;
}