giawa / opengl4csharp

OpenGL 4 Bindings (partially based on OpenTK) for C#
Other
232 stars 61 forks source link

Support additional numerical types #22

Closed TheAIBot closed 5 years ago

TheAIBot commented 5 years ago

VBO now support these additional types: sbyte, byte, short, ushort, int, uint, float and double. Added the following properties to VBO. bool CastToFloat: All supported types may be cast to float on the gpu. So an int and double will be converted to floats. If this is false then other types than float will not be cast to float. If you wish to use a vertex attribute of an integral type then this should be false. bool Normalize: Whether integral types should be normalized when cast to float.

Breaking changes

VAO now supports an element array with another type than int. You now has to specify which type the element array will be in the VAO type. So previous VAO<Vector3> is now VAO<Vector3, uint> Signed integral types are not valid element buffer types. I can move this part to its own pr if necessary.

Removed Divisor from the constructors of VBO. Divisor, along with CastToFloat and Normalize, are not part of the constructor. Instead of cluttering the constructors i decided to keep them as simple properties. I think it makes sense if all properties, that can be changed from outside the VBO, aren't part of the constructor. So essentially only readonly properties are part of the constructor.

giawa commented 5 years ago

Can we separate these? This looks like at least two different PRs. One could be for the new types and properties on the VBO, the other can be for the support of element arrays with non-int types.

I'm very nervous about the non-int type element arrays, not because they won't work, but because this is a pretty serious breaking change. It would be nice to offer backwards compatibility with the old VAO class. What do you think of allowing VAO<T1, T2, T3> to support either 4 VBOs (T1, T2, T3 and int type element array) or 3 VBOs with a custom element array data type (T1, T2 and T2 (T2 as the element array))? You can select which you prefer by using the constructor. For example:

    public class VAO<T1, T2, T3> : GenericVAO
        where T1 : struct
        where T2 : struct
        where T3 : struct
    {
        public VAO(ShaderProgram program, VBO<T1> vbo1, VBO<T2> vbo2, string[] attribNames, VBO<T3> elementArray)
            : base(program)
        {
            if (attribNames.Length != 2) 
                throw new Exception($"Expected an array of 2 names, but instead got {attribNames.Length}.");

            IGenericVBO[] vbos = new IGenericVBO[3];
            vbos[0] = new GenericVBO<T1>(vbo1, attribNames[0]);
            vbos[1] = new GenericVBO<T2>(vbo2, attribNames[1]);
            vbos[2] = new GenericVBO<T3>(elementArray, "");

            Init(vbos);
        }

        public VAO(ShaderProgram program, VBO<T1> vbo1, VBO<T2> vbo2, VBO<T3> vbo3, string[] attribNames, VBO<int> elementArray)
            : base(program)
        {
            if (attribNames.Length != 3) 
                throw new Exception($"Expected an array of 3 names, but instead got {attribNames.Length}.");

            IGenericVBO[] vbos = new IGenericVBO[4];
            vbos[0] = new GenericVBO<T1>(vbo1, attribNames[0]);
            vbos[1] = new GenericVBO<T2>(vbo2, attribNames[1]);
            vbos[2] = new GenericVBO<T3>(vbo3, attribNames[2]);
            vbos[3] = new GenericVBO<int>(elementArray, "");

            Init(vbos);
        }
    }

GenericVAO would stay without generics. BindAttributes would change to just look for any IGenericVBO that targets element array buffer:

        public void BindAttributes(ShaderProgram program)
        {
            IGenericVBO elementArray = null;

Curious on your thoughts. This would avoid a breaking change, while (I think) adding the support you are looking for.

TheAIBot commented 5 years ago

Yeah you are right. I removed VAO supporting multiple element array types from this pr.