Can I mix data types in buffers in OpenGL (C ++)?

I have an array of GLfloats, which I use as positions and colors when drawing squares (so there are 4 floats on top). I would like to add the ability to colorize my ATVs, and decided that I would pack RGBA in one GLuint and then send it to the GPU along with the positions.

So, can I somehow send 4 GLfloats and then 1 GLuint to the GPU?

Here is the relevant code:

void SpriteRenderer::Init() { vertexBufferArrayInserts = 0; hasBegun = GL_FALSE; glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAX_VERTEX_BUFFER_SIZE, 0, GL_STREAM_DRAW); glGenBuffers(1, &elementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * MAX_ELEMENT_BUFFER_SIZE, 0, GL_STREAM_DRAW); ////////////////////////////////////////////////////////////////////////// //LOAD SHADER, CREATE AND USE PROGRAM ////////////////////////////////////////////////////////////////////////// glGenVertexArrays(1, &vertexArrayObject); glBindVertexArray(vertexArrayObject); vertexShaderID = LoadShaderFromFile("Shader", GL_VERTEX_SHADER); fragmentShaderID = LoadShaderFromFile("Shader", GL_FRAGMENT_SHADER); shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShaderID); glAttachShader(shaderProgram, fragmentShaderID); glBindFragDataLocation(shaderProgram, 0, "outColor"); glLinkProgram(shaderProgram); glUseProgram(shaderProgram); shaderPosAttrib = glGetAttribLocation(shaderProgram, "position"); glVertexAttribPointer(shaderPosAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0); glEnableVertexAttribArray(shaderPosAttrib); shaderTexCoordAttrib = glGetAttribLocation(shaderProgram, "texCoord"); glVertexAttribPointer(shaderTexCoordAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 2)); glEnableVertexAttribArray(shaderTexCoordAttrib); shaderColorAttrib = glGetAttribLocation(shaderProgram, "Color"); glVertexAttribPointer(shaderColorAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); glEnableVertexAttribArray(shaderColorAttrib); shaderProjMatAttrib = glGetUniformLocation(shaderProgram, "projMat"); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); } void SpriteRenderer::Draw(Vector2<GLfloat> position, Rect clipRect) { //TOP LEFT vertexBufferArray[vertexBufferArrayInserts * 16] = position.X; vertexBufferArray[vertexBufferArrayInserts * 16 + 1] = position.Y; vertexBufferArray[vertexBufferArrayInserts * 16 + 2] = clipRect.GetLeftX() / 512.0f; vertexBufferArray[vertexBufferArrayInserts * 16 + 3] = clipRect.GetTopY() / 512.0f; colorBufferArray[vertexBufferArrayInserts * 4] = PackColor(255, 255, 255, 255); //TOP RIGHT vertexBufferArray[vertexBufferArrayInserts * 16 + 4] = position.X + clipRect.GetWidth(); vertexBufferArray[vertexBufferArrayInserts * 16 + 5] = position.Y; vertexBufferArray[vertexBufferArrayInserts * 16 + 6] = clipRect.GetRightX() / 512.0f; vertexBufferArray[vertexBufferArrayInserts * 16 + 7] = clipRect.GetTopY() / 512.0f; colorBufferArray[vertexBufferArrayInserts * 4 + 1] = PackColor(255, 255, 255, 255); //BOTTOM RIGHT vertexBufferArray[vertexBufferArrayInserts * 16 + 8] = position.X + clipRect.GetWidth(); vertexBufferArray[vertexBufferArrayInserts * 16 + 9] = position.Y + clipRect.GetHeight(); vertexBufferArray[vertexBufferArrayInserts * 16 + 10] = clipRect.GetRightX() / 512.0f; vertexBufferArray[vertexBufferArrayInserts * 16 + 11] = clipRect.GetBottomY() / 512.0f; colorBufferArray[vertexBufferArrayInserts * 4 + 2] = PackColor(255, 255, 255, 255); //BOTTOM LEFT vertexBufferArray[vertexBufferArrayInserts * 16 + 12] = position.X; vertexBufferArray[vertexBufferArrayInserts * 16 + 13] = position.Y + clipRect.GetHeight(); vertexBufferArray[vertexBufferArrayInserts * 16 + 14] = clipRect.GetLeftX() / 512.0f; vertexBufferArray[vertexBufferArrayInserts * 16 + 15] = clipRect.GetBottomY() / 512.0f; colorBufferArray[vertexBufferArrayInserts * 4 + 3] = PackColor(255, 255, 255, 255); //ELEMENT BUFFER elementBufferArray[vertexBufferArrayInserts * 6] = vertexBufferArrayInserts * 4; elementBufferArray[vertexBufferArrayInserts * 6 + 1] = vertexBufferArrayInserts * 4 + 1; elementBufferArray[vertexBufferArrayInserts * 6 + 2] = vertexBufferArrayInserts * 4 + 2; elementBufferArray[vertexBufferArrayInserts * 6 + 3] = vertexBufferArrayInserts * 4 + 2; elementBufferArray[vertexBufferArrayInserts * 6 + 4] = vertexBufferArrayInserts * 4 + 3; elementBufferArray[vertexBufferArrayInserts * 6 + 5] = vertexBufferArrayInserts * 4; vertexBufferArrayInserts++; if(vertexBufferArrayInserts == MAX_BUFFER_INSERTS) Draw(); } void SpriteRenderer::Draw() { glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * vertexBufferArrayInserts * 16, vertexBufferArray); glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertexBufferArrayInserts * 16, sizeof(GLuint) * vertexBufferArrayInserts * 4, colorBufferArray); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLint) * vertexBufferArrayInserts * 6, elementBufferArray); glDrawElements(GL_TRIANGLES, vertexBufferArrayInserts * 6, GL_UNSIGNED_INT, 0); vertexBufferArrayInserts = 0; } GLuint SpriteRenderer::PackColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { GLint returnVal = (r << 24) + (g << 16) + (b << 8) + a; return returnVal; } 
+4
source share
1 answer

Your problem is:

 glVertexAttribPointer(shaderColorAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); 

It will be unpacked as one component.

Tell the GPU that you are sending four single-byte components (which adds up to one 32-bit value):

 glVertexAttribPointer(shaderColorAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); 

Notice that I set the normalized flag to true. Do this if you send it to vec4 in the shader so that each component is converted to the range [0,1] that you most likely want.

Also, instead of doing very erroneous maths with sizeof(float) , consider creating a structure and using the size of this structure and offsetof to create step and vertex offsets:

 struct vertex { float4 position; ubyte4 color; }; glVertexAttribPointer(shaderColorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), offsetof(vertex, position)); glVertexAttribPointer(shaderColorAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(vertex), offsetof(vertex, color)); 

This becomes more critical after mixing data types. Just be aware of the laying of the structure; using offsetof ensures that everything works, but you don't want to waste the space of your buffer object.

+3
source

Source: https://habr.com/ru/post/1487362/


All Articles