2

基本的な 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;
}
4

3 に答える 3

1

いくつかのこと:

まず、投影行列の「目」を [0, 0 -1] に設定し、「カメラ」を画面の後ろに押しているようです。この場合、オブジェクトを表示するには、オブジェクトをそのポイントを超えて移動する必要があるのが普通です。

犯人の行は次のとおりです(変数名は特に明確ではないと思います:-/):

a[3 + 4 * 2] = -1.0f;

に変更してみます

a[3 + 4 * 2] = 1.0f;

そして、それが違いを生むかどうかを確認してください。

次に、レンダリングする内容によっては、「カメラ」がたまたまメッシュ内にある場合があります。背面カリングが有効になっているため、表示されているすべての面がカリングされ、モデルをさらに遠ざけると、カリングされていない面が表示されるため、まったく何も表示されません。これが問題かどうかを確認するには、行を変更します

glEnable(GL_CULL_FACE);

glDisable(GL_CULL_FACE);

「カメラ」がメッシュ内にあるかどうかを確認します。

第 3 に、メッシュが「カメラ」とニア プレーンの間にある可能性があります。zNear を試してみて、違いがあるかどうかを確認してください。オブジェクトを遠ざけるとオブジェクトが表示されるため、zFar はおそらく正しいでしょう。

編集:だから私はそれをより詳細に調べて、あなたの射影行列を理解しようとしました。透視投影の背後にある数学のこの優れた説明によると、射影行列生成コードは、-Z を見下ろす行列を生成するのに正しいようです。基本的に、OpenGL はデフォルトで右手座標系を使用するため、コードは期待どおりに機能します。

負の値が気になるため、オブジェクトを +Z でオフセットできるようにしたい場合は、Y 軸を中心に 180 度回転するビュー マトリックスを作成し、それを投影マトリックスで乗算することができます。あなたはそれから得るでしょう

finalCoordinates = projection * view * model * vertex;

TL;DR: あなたのコードは期待どおりに動作します。

于 2013-07-02T14:19:36.120 に答える