Я рисую круг в opengl и пытаюсь изменить экран камеры, чтобы показать круг.
Сначала я сделал круг с размером изображения, и превратил круг в треугольник и превратил его в VBO, и мне удалось вывести его на экран.
Однако,при просмотре преобразований с использованием матрицы MVP (модель, вид, проекция) треугольники окружности продолжают ломаться.
Ниже приведен мой код, основанный на http://www.opengl -tutorial.org / ru / beginners-tutorials / tutorial-3-matrices / коде.(Базовый код находится по адресу https://github.com/opengl-tutorials/ogl)
Я не знаю причину этой проблемы и хочу получить помощь.
мой код opengl
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.hpp>
#define PI 3.141592
#define TRI_POS_NUM 3
#define CIRCLE_RADIUS 350
#define X_INDEX 0
#define Y_INDEX 1
#define Z_INDEX 2
#define FIRST_TRI 0
#define SECOND_TRI 1
#define THIRD_TRI 2
#define IMG_WIDTH 1000
#define IMG_HEIGHT 1000
GLfloat *tri_pos_array; // array[2][TRI_POS_NUM] 2 is means X,Y
GLfloat *tri_array; // array[3][2][TRI_POS_NUM] 2 is means X,Y and 3 is means The number of coordinates that make up the triangle.
GLfloat *tri_vbo_array;
void convert_img_coord_to_vbo_coord(GLfloat *x, GLfloat *y, int cx, int cy, int img_width, int img_height);
void init_vbo_tri_pos_array(GLfloat *tri_pos_array, int circle_radius, int tri_pos_num, int img_width, int img_height);
void init_tri_array(GLfloat *tri_array, GLfloat *tri_pos_array, int tri_pos_num, int img_width, int img_height);
void init_tri_vbo_array(GLfloat *tri_array, GLfloat *tri_vbo_array, int tri_pos_num);
void set_gl_array(GLfloat *in_tri_array, GLfloat *out_gl_array, int tri_pos_num);
void convert_img_coord_to_vbo_coord(GLfloat *x, GLfloat *y, int cx, int cy, int img_width, int img_height)
{
GLfloat tmp_x = *x;
GLfloat tmp_y = *y;
float scale = 1.0;
*x = (tmp_x - cx) / img_width * scale;
*y = (tmp_y - cy) / img_height * scale;
}
void init_vbo_tri_pos_array(GLfloat *tri_pos_array, int circle_radius, int tri_pos_num, int img_width, int img_height)
{
GLfloat x_pos = 0;
GLfloat y_pos = 0;
int index = 0;
int cx = img_width / 2;
int cy = img_height / 2;
for (index; index < tri_pos_num; index++)
{
GLfloat theta = 2.0f * PI * GLfloat(index) / GLfloat(tri_pos_num);
x_pos = cosf(theta) * circle_radius;
y_pos = sinf(theta) * circle_radius;
x_pos += cx;
y_pos += cy;
convert_img_coord_to_vbo_coord(&x_pos, &y_pos, cx, cy, img_width, img_height);
tri_pos_array[X_INDEX * (tri_pos_num) + index] = x_pos;
tri_pos_array[Y_INDEX * (tri_pos_num) + index] = y_pos;
}
}
void init_tri_array(GLfloat *tri_array, GLfloat *tri_pos_array, int tri_pos_num, int img_width, int img_height)
{
int index = 0;
int cx = img_width / 2;
int cy = img_height / 2;
float z_value = 0.0f;
for (index; index < tri_pos_num - 1; index++)
{
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index ] = 0.0f; // 0.0f is mean's VBO Coordinate cx
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index ] = 0.0f; // 0.0f is mean's VBO Coordinate cy
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index ] = z_value; // 0.0f is mean's VBO Coordinate cy
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index] = tri_pos_array[X_INDEX * (tri_pos_num)+index];
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index] = tri_pos_array[Y_INDEX * (tri_pos_num)+index];
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index] = z_value;
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index] = tri_pos_array[(X_INDEX * (tri_pos_num)+index) + 1];
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index] = tri_pos_array[(Y_INDEX * (tri_pos_num)+index) + 1];
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index] = z_value;
}
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index] = 0.0f; // 0.0f is mean's VBO Coordinate cx
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index] = 0.0f; // 0.0f is mean's VBO Coordinate cy
tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index] = z_value; // 0.0f is mean's VBO Coordinate cy
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index] = tri_pos_array[X_INDEX * (tri_pos_num)+index];
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index] = tri_pos_array[Y_INDEX * (tri_pos_num)+index];
tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index] = z_value;
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index] = tri_pos_array[0];
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index] = tri_pos_array[tri_pos_num];
tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index] = z_value;
}
void set_gl_array(GLfloat *in_tri_array, GLfloat *out_gl_array, int tri_pos_num)
{
int index = 0;
//for(index; index < tri_pos_num -1 ; index++)
for(index; index < tri_pos_num ; index++)
{
out_gl_array[ (index * 9) + 0 ] = in_tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index ];
out_gl_array[ (index * 9) + 1 ] = in_tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index ];
out_gl_array[ (index * 9) + 2 ] = in_tri_array[(FIRST_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index ];
out_gl_array[ (index * 9) + 3 ] = in_tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index];
out_gl_array[ (index * 9) + 4 ] = in_tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index];
out_gl_array[ (index * 9) + 5 ] = in_tri_array[(SECOND_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index];
out_gl_array[ (index * 9) + 6 ] = in_tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (X_INDEX * (tri_pos_num)) + index];
out_gl_array[ (index * 9) + 7 ] = in_tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Y_INDEX * (tri_pos_num)) + index];
out_gl_array[ (index * 9) + 8 ] = in_tri_array[(THIRD_TRI * 2 * (tri_pos_num)) + (Z_INDEX * (tri_pos_num)) + index];
}
}
int main( void )
{
tri_pos_array = (GLfloat *)malloc( sizeof(GLfloat ) * 2 * TRI_POS_NUM);
tri_array = (GLfloat *)malloc( sizeof(GLfloat ) * 3 * 3 * TRI_POS_NUM);
tri_vbo_array = (GLfloat *)malloc( sizeof(GLfloat ) * 3 * 3 * TRI_POS_NUM);
init_vbo_tri_pos_array(tri_pos_array, CIRCLE_RADIUS, TRI_POS_NUM, IMG_WIDTH, IMG_HEIGHT);
init_tri_array(tri_array, tri_pos_array, TRI_POS_NUM, IMG_WIDTH, IMG_HEIGHT);
set_gl_array(tri_array, tri_vbo_array, TRI_POS_NUM);
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
// Open a window and create its OpenGL context
window = glfwCreateWindow( IMG_WIDTH, IMG_HEIGHT, "Tutorial 03 - Matrices", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleTransform.vertexshader", "SingleColor.fragmentshader" );
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Get a handle for our buffers
GLuint vertexPosition_modelspaceID = glGetAttribLocation(programID, "vertexPosition_modelspace");
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
//glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 Projection = glm::perspective(45.0f, (float) IMG_WIDTH/IMG_HEIGHT, 0.1f, 100.0f);
// Or, for an ortho camera :
//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(1.0f,1.0f,1.0f), // Camera is at (4,3,3), in World Space
glm::vec3(0.0f,0.0f,0.0f), // and looks at the origin
glm::vec3(0.0f,-1.0f,0.0f) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(2.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
static const GLushort g_element_buffer_data[] = { 0, 1, 2 };
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
//glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 3 * TRI_POS_NUM, tri_vbo_array, GL_STATIC_DRAW);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(vertexPosition_modelspaceID);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
vertexPosition_modelspaceID, // The attribute we want to configure
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
//glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
glDrawArrays(GL_TRIANGLES, 0, 3 * TRI_POS_NUM); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(vertexPosition_modelspaceID);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
мой вершинный шейдер "SimpleTransform.vertexshader"
#version 120
// Input vertex data, different for all executions of this shader.
attribute vec3 vertexPosition_modelspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
//gl_Position = vec4(vertexPosition_modelspace,1);
}
мой фрагментный шейдер "SingleColor.fragmentshader"
#version 120
// Ouput data
//out vec3 color;
void main()
{
// Output color = red, full opacity
gl_FragColor = vec4(1,0,0, 1);
}