我的任务是展示几张照片。我将其实现为一个类来创建几个实例。每个实例表示一幅图片。它编译着色器,设置两个三角形,并在构造函数中加载图片数据。主程序创建实例,然后转到循环,为每个实例切换prigramid和调用render()方法。
while(true)
for (uint g = 0; g < pictures.size(); g++){
glUseProgram(pictures[g]->ProgramId);
pictures[g]->render();
}它运行良好,并显示图片,但我不喜欢它。可以做得更好。
下面是类的部分代码
Picture::Picture(picPosition* pPosition, const char * fileName)
:BasePicture(pPosition)
{
pos = glGetAttribLocation(ProgramId, "position");
uv = glGetAttribLocation(ProgramId, "texture_vert");
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
int n;
textureData = stbi_load(fileName, &picWidth, &picHeight, &n, STBI_rgb_alpha);
TextureID = glGetUniformLocation(ProgramId, "myTextureSampler");
glBindTexture(GL_TEXTURE_2D, TextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE0);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//calculating the vertex matrix using MVP calculated in parent class
for (int i = 0; i < 6; i++)
ModeledVerts.push_back(MVP * verts[i]);
v = glm::value_ptr(ModeledVerts[0]);
}
Picture::~Picture()
{
stbi_image_free(textureData);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &uvbuffer);
}
void Picture::render()
{
glBufferData(GL_ARRAY_BUFFER, 96, v, GL_STATIC_DRAW);
glVertexAttribPointer(pos, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*) 0);
glEnableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesUV), verticesUV, GL_STATIC_DRAW);
glVertexAttribPointer(uv, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*) 0);
glEnableVertexAttribArray(uv);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picWidth, picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
glDrawArrays(GL_TRIANGLES, 0, 6);
}我经常使用代码来使render()函数尽可能轻巧,但我不能使它比现在更轻。
最大的问题是每次发送textureData (glTexImage2D)。数据从未改变过。我试图将其移动到构造函数,但在本例中,所有图片对象都显示了最新加载的图片。看起来有一个实例覆盖了之前上传的纹理数据。我正在寻找一种方法来加载图片数据一次在构造函数,而不是每次它呈现。看起来这方面的OpenGL API中有一些东西,但我还不知道。
另一个改进是获取从render()中设置的顶点数据。数据永远不会变。但它并不像glTexImage2D在render()中调用的那样重要。
你能给我指一下OpenGL API来分离着色器的数据吗?或者告诉我我做错了什么。
发布于 2018-12-30 05:48:47
回答我自己的问题。解决办法是使用地图集地图。软件生成包含所有图片的地图集,上传一次(glTexImage2D)并对每幅图片使用坐标。这大大提高了性能,因为只调用了一次glTexImage2D。
发布于 2018-02-02 03:15:26
你说:
它运行良好,并显示图片,但我不喜欢它。可以做得更好。
从设计的角度来看,我认为这可能对你有帮助。
将打开、读取和解析纹理数据的图像文件的功能与实际的纹理结构或类分开。这将是一个示例伪代码:
struct Texture {
unsigned int width;
unsigned int height;
bool hasTransparency;
GLint id; // ID that is used by OpenGL to setActive, bind, and pass to shaders as either a uniform or sampler2D.
std::string filenameAndPath; // Keep this filename associated with texture so you can prevent trying to reload the same file over and over.
GLuchar* data; // the actual color - pixel texture data.
}
// This function will handle the opening and reading in of the texture data
// it would return back the ID value generated by OpenGL which will also be
// stored into the texture struct. The texture struct is returned by reference so that it can be populated with data.
GLuint loadTexture( const char* filenameAndPath, Texture& texture, /*loading parameters & flags*/ ) {
// Check to see if file exists or is already loaded
if ( fileanameAndPath already exists ) {
// get the existing ID from the already loaded texture
// and just return that.
} else {
// Try to open the new file for reading.
// parse the data for general purposes that will support
// your application. You can simply use `stbi_load` as it is a fairly
// decent third party library.
// Check the internal formatting of how the data is stored
// Compression, pixel orientation etc.
// configure the data to your needs (color format),
// (flipping the pixels either horizontally, vertically or both),
// now copy the actual pixel data into your buffer.
// close the file handle
// save all the information into your struct
// return the ID value that was generated by OpenGL
}
}在render loop之前的主引擎代码中,您需要从文件中加载纹理,然后您可以在需要的地方使用这个纹理对象。最后,在渲染循环中,您需要将纹理设置为活动,并将它们绑定到渲染目标,并将它们传递给您的着色器。在某些情况下,您可能希望将它们设置为active &在render loop之前绑定它们,具体取决于要实现的shader-technique类型。
https://stackoverflow.com/questions/48574909
复制相似问题