OpenGLで線を描きたいです。
glBegin(GL_LINES);
glVertex2f(.25,0.25);
glVertex2f(.75,.75);
glEnd();
このコードは線を描画しますが、座標 (10,10) から座標 (20,20) まで線を描画したい場合はどうすればよいでしょうか?
(.25, .25) と (.75, .75) はどういう意味ですか?
ベストアンサー1
OpenGL2の場合:
の各ポイントの値はglVertex2f
-1 から 1 の間であり、左下は (-1, -1)、右上は (1,1)、中央は (0, 0) です。
絶対点を正規化された空間にマッピングするには:
x
をウィンドウ幅で割ってw
、0 から 1 の範囲の点を取得します。0 から 2 までの範囲を取得するには、2 を掛けます。
1 を減算すると、目的の -1 ~ 1 の範囲が得られます。
y
値とウィンドウの高さについても繰り返しますh
。
例えば:
double x1 = 10;
double y1 = 10;
double x2 = 20;
double y2 = 20;
x1 = 2*x1 / w - 1;
y1 = 2*y1 / h - 1;
x2 = 2*x2 / w - 1;
y2 = 2*y2 / h - 1;
glBegin(GL_LINES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glEnd();
OpenGL3+の場合:プログラム可能なパイプラインを使用して線を描くのは、少し複雑です。2Line
つの点を取得して GPU に送信し、単純なシェーダー プログラムで描画するクラスを作成できます。すべてのセットアップはコンストラクターで実行でき、いくつかのアクセス関数で変更できます。
class Line {
int shaderProgram;
unsigned int VBO, VAO;
vector<float> vertices;
vec3 startPoint;
vec3 endPoint;
mat4 MVP;
vec3 lineColor;
public:
Line(vec3 start, vec3 end) {
startPoint = start;
endPoint = end;
lineColor = vec3(1,1,1);
MVP = mat4(1.0f);
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 MVP;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec3 color;\n"
"void main()\n"
"{\n"
" FragColor = vec4(color, 1.0f);\n"
"}\n\0";
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
// link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
vertices = {
start.x, start.y, start.z,
end.x, end.y, end.z,
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
int setMVP(mat4 mvp) {
MVP = mvp;
return 1;
}
int setColor(vec3 color) {
lineColor = color;
return 1;
}
int draw() {
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "MVP"), 1, GL_FALSE, &MVP[0][0]);
glUniform3fv(glGetUniformLocation(shaderProgram, "color"), 1, &lineColor[0]);
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, 2);
return 1;
}
~Line() {
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
}
};
でいくつかの 3D ラインを初期化しLine line(vec3 ..., vec3 ...)
、モデル ビュー投影行列line.setMVP(projection * view * model)
とを設定しline.draw()
、カメラを回転すると、次のようなものが生成されます。
注記:必要なのが 2D ラインだけであれば、z 値を 0 に設定して vec3 終点座標を指定し、呼び出しから投影マトリックスを削除しsetMVP
、カメラの位置を (0,0,0) に設定するだけです。OpenGL2 で上で説明したように、2D ラインの描画にも同じことが当てはまるため、座標は NDC 空間で OpenGL に送信する必要があります。