| 17 | } |
| 18 | |
| 19 | GL46InputLayout::GL46InputLayout(GLuint, GLuint vbufferHandle, VertexBuffer const* vbuffer) |
| 20 | : |
| 21 | mVBufferHandle(vbufferHandle), |
| 22 | mVArrayHandle(0), |
| 23 | mNumAttributes(0), |
| 24 | mAttributes{} |
| 25 | { |
| 26 | glGenVertexArrays(1, &mVArrayHandle); |
| 27 | glBindVertexArray(mVArrayHandle); |
| 28 | |
| 29 | if (vbuffer) |
| 30 | { |
| 31 | VertexFormat const& format = vbuffer->GetFormat(); |
| 32 | mNumAttributes = format.GetNumAttributes(); |
| 33 | for (int32_t i = 0; i < mNumAttributes; ++i) |
| 34 | { |
| 35 | Attribute& attribute = mAttributes[i]; |
| 36 | |
| 37 | DFType type{}; |
| 38 | uint32_t unit{}, offset{}; |
| 39 | format.GetAttribute(i, attribute.semantic, type, unit, offset); |
| 40 | |
| 41 | attribute.numChannels = static_cast<GLint>( |
| 42 | DataFormat::GetNumChannels(type)); |
| 43 | attribute.channelType = |
| 44 | msChannelType[DataFormat::GetChannelType(type)]; |
| 45 | attribute.normalize = static_cast<GLboolean>( |
| 46 | DataFormat::ConvertChannel(type) ? 1 : 0); |
| 47 | attribute.location = i; // layouts must be zero-based sequential |
| 48 | attribute.offset = static_cast<GLintptr>(offset); |
| 49 | attribute.stride = static_cast<GLsizei>(format.GetVertexSize()); |
| 50 | |
| 51 | glEnableVertexAttribArray(attribute.location); |
| 52 | glBindVertexBuffer(i, mVBufferHandle, attribute.offset, |
| 53 | attribute.stride); |
| 54 | glVertexAttribFormat(attribute.location, attribute.numChannels, |
| 55 | attribute.channelType, attribute.normalize, 0); |
| 56 | glVertexAttribBinding(attribute.location, i); |
| 57 | } |
| 58 | glBindVertexArray(0); |
| 59 | } |
| 60 | else |
| 61 | { |
| 62 | LogError("Invalid inputs to GL46InputLayout constructor."); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | void GL46InputLayout::Enable() |
| 67 | { |
nothing calls this directly
no test coverage detected