cginternals / globjects

C++ library strictly wrapping OpenGL objects.
https://globjects.org
MIT License
538 stars 59 forks source link

Some suggestions #321

Open ghost opened 7 years ago

ghost commented 7 years ago

I suggest some semantics:

  1. Uniform equal operator

    uniform = glm::vec3(0.0f); //also updates shaders
  2. Attribute restrict types

    vao.format<glm::vec3>(bindingID, /* may have additional settings */);
  3. Buffer with types

Buffer<float> buffer; 
buffer.storage(256); //i.e. 256 floats
buffer.specialize(SSBO); //sorry for wrong enum name
float * mapped = buffer.data(); //don't forget set map flags before
buffer.unmap(); //Opengl conflict resolve
buffer[0] = 1.0f; //Auto map, don't forget unmap
ghost commented 7 years ago

Also, I have question: why identation jumping?

scheibel commented 7 years ago

Thanks for your feedback. Currently I'm a bit busy but I will definitely go into detail for your three suggestions later.

What I'm currently wondering right now is the definition of "identation jumping". Do you mean "indentation jumping"? Either way, I don't know if I understand this correctly. If this should mean that we use different representations of one indent in source code (4 spaces vs. tabs vs. other number of spaces), this is by accident. The whole source code should use 4 spaces for indentation.

cgcostume commented 7 years ago

"indentation jumping" is probably referring to inconsistent indentation of several files such as File.cpp

ghost commented 7 years ago

I want unify principles of my PhantomGL and globjects and make by team "globjects-2.0.0" Also, I separated texture types (2D, 3D, and unified by inheritance and templates), typed buffers, used newer OpenGL API... And even have context class. Also, I maked support for descriptors inside classes/objects. I made chaining. But... I also made header-only with support C OpenGL loaders. PhantomGL very, VERY young...

scheibel commented 7 years ago

I just had a quick look at your code: looks cool. It seems as if you're trying to provide one library to encapsulate typical problems with OpenGL programming (context management, opengl programming, use-case specific interfaces). Although harder to start with, we decided to design a library that doesn't restrict actual possible usage of OpenGL. We provide multiple libraries for separate problem domains, too.

scheibel commented 7 years ago

My opinions for your three suggestions:

  1. This may actually be useful and should have the same semantics as Uniform::set(const T & value).

  2. Providing such an interface for the VAO would impose a restriction in the usage. Although your use case may be the most common one, VAO configurations can become pretty complex and I don't want to provide multiple interfaces with different usage scenarios and semantics for the same underlying concept. A rendering engine however can build up on top of globjects and introduce such convenience functions. An example of a more complex VAO configuration (here in plain OpenGL):

    
    glBindVertexArray(m_vao);

glBindBuffer(GL_ARRAY_BUFFER, m_vertices); glBufferData(GL_ARRAY_BUFFER, (verticesCount()+2) * vertexByteSize(), nullptr, GL_STATIC_DRAW);

glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 0, sizeof(glm::vec3), &emptyVec3); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 0 + sizeof(glm::vec3), verticesCount() sizeof(glm::vec3), m_position.data()); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) * 3 - sizeof(glm::vec3), sizeof(glm::vec3), &emptyVec3);

glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 3, sizeof(int), &emptyInt); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 3 + sizeof(int), verticesCount() sizeof(int), m_trajectoryID.data()); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) * 4 - sizeof(int), sizeof(int), &emptyInt);

glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 4, sizeof(int), &emptyInt); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 4 + sizeof(int), verticesCount() sizeof(int), m_type.data()); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) * 5 - sizeof(int), sizeof(int), &emptyInt);

glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 5, sizeof(float), &emptyFloat); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 5 + sizeof(float), verticesCount() sizeof(float), m_colorValue.data()); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) * 6 - sizeof(float), sizeof(float), &emptyFloat);

glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 6, sizeof(float), &emptyFloat); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) 6 + sizeof(float), verticesCount() sizeof(float), m_sizeValue.data()); glBufferSubData(GL_ARRAY_BUFFER, (verticesCount()+2) sizeof(float) * 7 - sizeof(float), sizeof(float), &emptyFloat);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 0 + sizeof(glm::vec3))); glVertexAttribIPointer(1, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(int) 3 + sizeof(int))); glVertexAttribIPointer(2, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(int) 4 + sizeof(int))); glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 5 + sizeof(float))); glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) * 6 + sizeof(float)));

// Previous values glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 0 + sizeof(glm::vec3) - sizeof(glm::vec3))); glVertexAttribIPointer(6, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 3 + sizeof(int) - sizeof(int))); glVertexAttribIPointer(7, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 4 + sizeof(int) - sizeof(int))); glVertexAttribPointer(8, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 5 + sizeof(float) - sizeof(float))); glVertexAttribPointer(9, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) * 6 + sizeof(float) - sizeof(float)));

// Next values glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 0 + sizeof(glm::vec3) + sizeof(glm::vec3))); glVertexAttribIPointer(11, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 3 + sizeof(int) + sizeof(int))); glVertexAttribIPointer(12, 1, GL_INT, sizeof(int), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 4 + sizeof(int) + sizeof(int))); glVertexAttribPointer(13, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) 5 + sizeof(float) + sizeof(float))); glVertexAttribPointer(14, 1, GL_FLOAT, GL_FALSE, sizeof(float), reinterpret_cast<void>((verticesCount()+2) sizeof(float) * 6 + sizeof(float) + sizeof(float)));

glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); glEnableVertexAttribArray(7); glEnableVertexAttribArray(8); glEnableVertexAttribArray(9); glEnableVertexAttribArray(10); glEnableVertexAttribArray(11); glEnableVertexAttribArray(12); glEnableVertexAttribArray(13); glEnableVertexAttribArray(14);

glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0);


3. Here you suggest a similar restriction during compile-time. An OpenGL buffer may change types (data types, e.g., float, structs, ints), usage (Vertex Buffer, SSBO, ...) and even semantics, i.e., a buffer object can be reused in completely different parts of a program and programmers are even encouraged to lower the number of object names in their program to a minimum.
However, some of those convenience functions you suppose are indirectly supported by globjects by the use of the C++ stdlib. Using current globjects, I can write the first part of your code as follows:
```cpp
auto buffer = new globjects::Buffer;
auto data = std::vector<float>(256); // 256 floats
buffer->setData(data, GL_STATIC_DRAW);

You further suggest that some parameters should be configured beforehand that are used during the actual function call (mapping parameters, binding points). A rendering engine using globjects can provide such interface, we want to provide a smaller interface that can be mapped onto actual OpenGL functions (at minimum one OpenGL function call per globjects method or function).

ghost commented 7 years ago

Some states I changed in my library, but generally - I have same ideas....

  1. Buffer can be untyped... But typed have anyways, differs by inheritance
  2. VAO can autodetect types, and also have binding API
  3. Uniforms can assign, and also can accept additional values
  4. We have texture specializations
  5. We extremely extended getting of OpenGL parameters, but anyway not ideal at now
  6. Attribute objects also can describe types