编写了一个类,让您无需大量代码即可快速绘制飞机。但是几十架飞机,一切都在几秒钟内冻结了一秒钟。我究竟做错了什么。
请注意,该类仅用于显示正方形,每个正方形都有自己的纹理,不适用于模型。
我将添加一点问题,如何正确绘制每个帧都是唯一的网格,因为它在 OpenGL 2.0 中仅在标准中。OpenGL 3.0
class Plane3_3
{
public:
//Шейдер программа
GLuint shaderProgramPlane;
//Структура одного полигона
struct Mesh
{
GLuint Texture;
GLuint VAOparam,VBOpoints;
int Size;
float R,G,B,A;
};
//Временный масив для компиляции в VAO
vector<GLfloat>Vertex2D;
//Набор меша
std::vector<Mesh>ArrMesh;
//Екземпляр набора для сброса в масив
Mesh Temp;
//Задать цвет
void Color4f(float R,float G,float B,float A)
{
Temp.R = R;
Temp.G = G;
Temp.B = B;
Temp.A = A;
}
//Задать цвет в диапазоне - 255
void Color4uf(float R,float G,float B,float A)
{
Temp.R = R/255;
Temp.G = G/255;
Temp.B = B/255;
Temp.A = A/255;
}
//Очистить временные переменные задать текстуру изза нее и цвета не могу месш вклеить в один vao
void Begin(GLuint Texture)
{
Vertex2D.clear();
Temp.VAOparam = 0;
Temp.VBOpoints = 0;
Temp.Texture = Texture;
}
//Отрендорить (Скомпилировать) и сбросить в масив
void End()
{
//Создать VAO буфер
glGenVertexArrays(1,&Temp.VAOparam);
//Создать VBO буфер
glGenBuffers(1,&Temp.VBOpoints);
//Активировать VAO Буфер
glBindVertexArray(Temp.VBOpoints);
//Активировать VBO Буфер и связать переменную с буфером
glBindBuffer(GL_ARRAY_BUFFER,Temp.VBOpoints);
//Скопировать (координаты) в VBO == GL_ARRAY_BUFFER
glBufferData(GL_ARRAY_BUFFER,sizeof(float)*Vertex2D.size(),&Vertex2D[0],GL_STREAM_DRAW); //GL_STATIC_DRAW GL_DYNAMIC_DRAW GL_STREAM_DRAW
//Как шейдер должен распознать точку Текстурные координаты
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,4*sizeof(GL_FLOAT),(GLvoid*)0);
//Активировать индекс layout
glEnableVertexAttribArray(0);
//Как шейдер должен распознать точку координаты
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,4*sizeof(GL_FLOAT),(GLvoid*)(2 * sizeof(GL_FLOAT)));
//Активировать индекс layout
glEnableVertexAttribArray(1);
//деактивирую наверное VBO Буфер
glBindBuffer(GL_ARRAY_BUFFER,0);
//деактивирую наверное VAO буфер
glBindVertexArray(0);
Temp.Size = Vertex2D.size()/4;
//Сброс в масив
ArrMesh.push_back(Temp);
}
//Создать шейдер
void CreateShader()
{//--------------------------------
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar* vertexShaderSourse = "#version 330 core\n"
"layout(location=0) in vec2 TextCord;\n"
"layout(location=1) in vec2 position;\n"
"out vec2 TexCoords;\n"
"void main()\n"
"{\n"
"TexCoords = TextCord;\n"
"gl_Position = vec4(position.x,position.y,0,1);\n"
"}\0";
glShaderSource(vertexShader,1,&vertexShaderSourse,NULL);
glCompileShader(vertexShader);
{
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(vertexShader,512,NULL,infoLog);
std::cout<<"error vertex shader"<<std::endl<<infoLog<<std::endl;
}
}
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* fragmentShaderSourse = "#version 330 core\n"
"out vec4 color;\n"
"in vec2 TexCoords;\n"
"uniform sampler2D ourTexture;\n"
"uniform vec4 colorUS;\n"
"void main()\n"
"{\n"
"color = texture(ourTexture, TexCoords)*colorUS;\n"
"}\n"
"\0";
glShaderSource(fragmentShader,1,&fragmentShaderSourse,NULL);
glCompileShader(fragmentShader);
{
GLint success;
GLchar infoLog[512];
glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(fragmentShader,512,NULL,infoLog);
std::cout<<"Fragment Error"<<std::endl<<infoLog<<std::endl;
}
}
shaderProgramPlane = glCreateProgram();
glAttachShader(shaderProgramPlane,vertexShader);
glAttachShader(shaderProgramPlane,fragmentShader);
glLinkProgram(shaderProgramPlane);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
{
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgramPlane,GL_LINK_STATUS,&success);
if(!success)
{
glGetProgramInfoLog(shaderProgramPlane,512,NULL,infoLog);
std::cout<<"error shader"<<std::endl<<infoLog<<std::endl;
}
}
}//--------------------------------
//Добавить точку
void AddPoint(float tx, float ty,float x,float y)
{
Vertex2D.push_back(tx);
Vertex2D.push_back(ty);
Vertex2D.push_back(x);
Vertex2D.push_back(y);
}
//Рисовать все
void Draw()
{
//Активировать шейдер
glUseProgram(shaderProgramPlane);
for(int i = 0; i<ArrMesh.size();i++)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ArrMesh[i].Texture);
glUniform1i(glGetUniformLocation(shaderProgramPlane, "ourTexture"), 0);
glUniform4f(glGetUniformLocation(shaderProgramPlane, "colorUS"), ArrMesh[i].R,ArrMesh[i].G,ArrMesh[i].B,ArrMesh[i].A);
//Активировать vao
glBindVertexArray(ArrMesh[i].VAOparam);
//Рисовать масив
glDrawArrays(GL_TRIANGLES,0,ArrMesh[i].Size);
//Не понятно вроде деактивирую
glBindVertexArray(0);
}
}
//Очистить все
void Clear()
{
for(int i = 0; i<ArrMesh.size();i++)
{
glDeleteVertexArrays(1,&ArrMesh[i].VAOparam);
glDeleteBuffers(1,&ArrMesh[i].VBOpoints);
}
ArrMesh.clear();
}
Plane3_3()
{
Temp.R = 1;
Temp.G = 1;
Temp.B = 1;
Temp.A = 1;
}
~Plane3_3()
{
}
};
/// 决定走另一条路。这些点是静态的,正方形只收集一次,然后使用着色器修改为所需的点。
/*
Керування через шейдер замість меша напряму (рендор мешів лагає)
Предається стандартний меш координати 1 1
Текстурні координати 1 1
В такому випадку в шейдер ми передаємо координати меша і текстурного квадрата
Передеємо розміри обох кубів.
*/
class Square
{
public:
//Шейдер программа
GLuint shaderProgramPlane;
//Создать шейдер
void CreateShader()
{//--------------------------------
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar* vertexShaderSourse = "#version 330 core\n"
"layout(location=0) in vec2 TextCord;\n"
"layout(location=1) in vec2 position;\n"
"uniform vec2 S;\n"
"uniform vec2 P;\n"
"out vec2 TexCoords;\n"
"void main()\n"
"{\n"
"TexCoords = TextCord;\n"
"gl_Position = vec4(position.x*S.x+P.x,position.y*S.y+P.y,0,1);\n"
"}\0";
glShaderSource(vertexShader,1,&vertexShaderSourse,NULL);
glCompileShader(vertexShader);
{
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(vertexShader,512,NULL,infoLog);
std::cout<<"error vertex shader"<<std::endl<<infoLog<<std::endl;
}
}
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* fragmentShaderSourse = "#version 330 core\n"
"out vec4 color;\n"
"in vec2 TexCoords;\n"
"uniform sampler2D ourTexture;\n"
"uniform vec4 colorUS;\n"
"uniform int textureEnable;\n"
"uniform vec2 Stx;\n" //Розміркуба текстурних кординат
"uniform vec2 Ptx;\n" //Зміщення текстурних координат, через шейдер
"void main()\n"
"{\n"
"vec2 TC = TexCoords;\n"
"TC.x = TC.x * Stx.x + Ptx.x;\n"
"TC.y = TC.y * Stx.y + Ptx.y;\n"
// "TexCoords.y = (TexCoords.y*Stx.y)+Ptx.y;\n"
"if(textureEnable)\n"
"color = texture(ourTexture, TC)*colorUS;\n"
"else\n"
"color = colorUS;\n"
"}\n"
"\0";
glShaderSource(fragmentShader,1,&fragmentShaderSourse,NULL);
glCompileShader(fragmentShader);
{
GLint success;
GLchar infoLog[512];
glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(fragmentShader,512,NULL,infoLog);
std::cout<<"Fragment Error"<<std::endl<<infoLog<<std::endl;
}
}
shaderProgramPlane = glCreateProgram();
glAttachShader(shaderProgramPlane,vertexShader);
glAttachShader(shaderProgramPlane,fragmentShader);
glLinkProgram(shaderProgramPlane);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
{
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgramPlane,GL_LINK_STATUS,&success);
if(!success)
{
glGetProgramInfoLog(shaderProgramPlane,512,NULL,infoLog);
std::cout<<"error shader"<<std::endl<<infoLog<<std::endl;
}
}
}//--------------------------------
GLuint VAOparam,VBOpoints;
void Comp()
{
//Создать VAO буфер
glGenVertexArrays(1,&VAOparam);
//Создать VBO буфер
glGenBuffers(1,&VBOpoints);
std::vector<float> Vertex2D;
//Point A
//tx
Vertex2D.push_back(0);
//ty
Vertex2D.push_back(0);
//x
Vertex2D.push_back(-0.5);
//y
Vertex2D.push_back(-0.5);
//Point B
//tx
Vertex2D.push_back(1);
//ty
Vertex2D.push_back(0);
//x
Vertex2D.push_back(0.5);
//y
Vertex2D.push_back(-0.5);
//Point C
//tx
Vertex2D.push_back(1);
//ty
Vertex2D.push_back(1);
//x
Vertex2D.push_back(0.5);
//y
Vertex2D.push_back(0.5);
//Point C
//tx
Vertex2D.push_back(1);
//ty
Vertex2D.push_back(1);
//x
Vertex2D.push_back(0.5);
//y
Vertex2D.push_back(0.5);
//Point A
//tx
Vertex2D.push_back(0);
//ty
Vertex2D.push_back(0);
//x
Vertex2D.push_back(-0.5);
//y
Vertex2D.push_back(-0.5);
//Point D
//tx
Vertex2D.push_back(0);
//ty
Vertex2D.push_back(1);
//x
Vertex2D.push_back(-0.5);
//y
Vertex2D.push_back(0.5);
//Активировать VAO Буфер
glBindVertexArray(VBOpoints);
//Активировать VBO Буфер и связать переменную с буфером
glBindBuffer(GL_ARRAY_BUFFER,VBOpoints);
//Скопировать (координаты) в VBO == GL_ARRAY_BUFFER
glBufferData(GL_ARRAY_BUFFER,sizeof(float)*Vertex2D.size(),&Vertex2D[0],GL_STATIC_DRAW); //GL_STATIC_DRAW GL_DYNAMIC_DRAW GL_STREAM_DRAW
//Как шейдер должен распознать точку Текстурные координаты
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,4*sizeof(GL_FLOAT),(GLvoid*)0);
//Активировать индекс layout
glEnableVertexAttribArray(0);
//Как шейдер должен распознать точку координаты
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,4*sizeof(GL_FLOAT),(GLvoid*)(2 * sizeof(GL_FLOAT)));
//Активировать индекс layout
glEnableVertexAttribArray(1);
//деактивирую наверное VBO Буфер
glBindBuffer(GL_ARRAY_BUFFER,0);
//деактивирую наверное VAO буфер
glBindVertexArray(0);
}
//Розмір і позиція куба
float SX,SY,X,Y;
void SetSizeAndPos(float sx,float sy,float x,float y)
{
SX = sx;
SY = sy;
X = x;
Y = y;
}
bool TextureEnable;
void SetTextureEnable(bool Enable)
{
TextureEnable = Enable;
}
//Розмір і позиця текстури
float txSX,txSY,txX,txY;
void SetTxSizeAndPos(float sx,float sy,float x,float y)
{
txSX = sx;
txSY = sy;
txX = x;
txY = y;
}
void Draw(GLuint Texture,float R,float G,float B,float A)
{
//Активировать шейдер
glUseProgram(shaderProgramPlane);
if(TextureEnable)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(glGetUniformLocation(shaderProgramPlane, "ourTexture"), 0);
}
glUniform1i(glGetUniformLocation(shaderProgramPlane, "textureEnable"), TextureEnable);
glUniform4f(glGetUniformLocation(shaderProgramPlane, "colorUS"), R/255,G/255,B/255,A/255);
glUniform2f(glGetUniformLocation(shaderProgramPlane, "S"), SX,SY);
glUniform2f(glGetUniformLocation(shaderProgramPlane, "P"), X,Y);
glUniform2f(glGetUniformLocation(shaderProgramPlane, "Stx"), txSX,txSY);
glUniform2f(glGetUniformLocation(shaderProgramPlane, "Ptx"), txX,txY);
//glUniform1f(glGetUniformLocation(shaderProgramPlane, "sx"), SX);
//glUniform1f(glGetUniformLocation(shaderProgramPlane, "sy"), SY);
//Активировать vao
glBindVertexArray(VAOparam);
//Рисовать масив
glDrawArrays(GL_TRIANGLES,0,6);
//Не понятно вроде деактивирую
glBindVertexArray(0);
}
Square()
{
}
~Square()
{
}
};
//Функція малює квадрат по координатам Ця функція для 2.0 стандарту але користувач може вказати свою
void UserOpenGL3_3_DrawPlane(bool TextureEnable,GLuint TextureID,double x1,double y1,double tx1,double ty1,double x2,double y2,double tx2,double ty2,double x3,double y3,double tx3,double ty3,double x4,double y4,double tx4,double ty4,double R,double G,double B,double A)
{
Square1.SetSizeAndPos(x2-x1,y4-y1,(x1+x2+x3+x4)/4,(y1+y2+y3+y4)/4);
Square1.SetTxSizeAndPos(tx2-tx1,ty4-ty1,tx1,ty1);
Square1.SetTextureEnable(TextureEnable);
Square1.Draw(TextureID,R,G,B,A);
}
这些东西速度不快,也不应该每方都做,否则就挂一百了。
您需要设置一次参数,然后绘制很多对象。
每一帧都会改变的网格可以这样绘制:
每一帧:
По идее нужен DYNAMIC_DRAW но серавно эта штука у меня только для отладки.
Для шейдера я использую https://gitlab.com/nikitasamoukov/codegenshaders и обращения к _shader_color, это по факту вызовы glUseProgram и glUniformXXX.
vec3 из glm.