diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100755 index 0000000..608d3c6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}" + } + ] +} \ No newline at end of file diff --git a/buffers/buffers.go b/buffers/buffers.go index c7c1122..2927e96 100755 --- a/buffers/buffers.go +++ b/buffers/buffers.go @@ -2,34 +2,111 @@ package buffers import ( "github.com/bloeys/go-sdl-engine/logging" - "github.com/bloeys/go-sdl-engine/shaders" "github.com/go-gl/gl/v4.6-compatibility/gl" ) -func HandleBuffers(sp shaders.ShaderProgram) { +type BufferType int - //Create and fill Vertex buffer object +const ( + BufTypeUnknown BufferType = iota + BufTypeVertPos + BufTypeColor +) + +type BufferGLType int + +const ( + //Generic array of data. Should be used for most data like vertex positions, vertex colors etc. + BufGLTypeArrayBuffer BufferGLType = gl.ARRAY_BUFFER +) + +type BufferUsage int + +const ( + //Buffer is set only once and used many times + BufUsageStatic BufferUsage = gl.STATIC_DRAW + //Buffer is changed a lot and used many times + BufUsageDynamic BufferUsage = gl.DYNAMIC_DRAW + //Buffer is set only once and used by the GPU at most a few times + BufUsageStream BufferUsage = gl.STREAM_DRAW +) + +type Buffer struct { + ID uint32 + Type BufferType + GLType BufferGLType + DataTypeInfo +} + +func (b *Buffer) Activate() { + gl.BindBuffer(uint32(b.GLType), b.ID) +} + +func (b *Buffer) Deactivate() { + gl.BindBuffer(uint32(b.GLType), 0) +} + +type BufferObject struct { + VAOID uint32 + VertPosBuf *Buffer + ColorBuf *Buffer +} + +func (bo *BufferObject) GenBuffer(data []float32, bufUsage BufferUsage, bufType BufferType, bufDataType DataType) { + + gl.BindVertexArray(bo.VAOID) + + //Create vertex buffer object var vboID uint32 gl.CreateBuffers(1, &vboID) if vboID == 0 { logging.ErrLog.Println("Failed to create openGL buffer") } - gl.BindBuffer(gl.ARRAY_BUFFER, vboID) - - vertices := []float32{ - -0.5, 0.5, 0, - 0.5, 0.5, 0, - -0.5, -0.5, 0, - - 0.5, 0.5, 0, - 0.5, -0.5, 0, - -0.5, -0.5, 0, + buf := &Buffer{ + ID: vboID, + Type: bufType, + GLType: BufGLTypeArrayBuffer, + DataTypeInfo: GetDataTypeInfo(bufDataType), } - gl.BufferData(gl.ARRAY_BUFFER, 4*len(vertices), gl.Ptr(vertices), gl.STATIC_DRAW) + bo.SetBuffer(buf) - //Assign the VBO to vertPos attribute - vertPosLoc := sp.GetAttribLoc("vertPos") - gl.VertexAttribPointer(uint32(vertPosLoc), 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) - gl.EnableVertexAttribArray(uint32(vertPosLoc)) + //Fill buffer with data + gl.BindBuffer(uint32(buf.GLType), buf.ID) + gl.BufferData(uint32(buf.GLType), int(buf.DataTypeInfo.ElementSize)*len(data), gl.Ptr(data), uint32(bufUsage)) + + //Unbind everything + gl.BindVertexArray(0) + gl.BindBuffer(uint32(buf.GLType), 0) +} + +func (bo *BufferObject) SetBuffer(buf *Buffer) { + + switch buf.Type { + case BufTypeVertPos: + bo.VertPosBuf = buf + case BufTypeColor: + bo.ColorBuf = buf + default: + logging.WarnLog.Println("Unknown buffer type in SetBuffer. Type:", buf.Type) + } +} + +func (bo *BufferObject) Activate() { + gl.BindVertexArray(bo.VAOID) +} + +func (bo *BufferObject) Deactivate() { + gl.BindVertexArray(0) +} + +func NewBufferObject() *BufferObject { + + var vaoID uint32 + gl.CreateVertexArrays(1, &vaoID) + if vaoID == 0 { + logging.ErrLog.Println("Failed to create openGL vertex array object") + } + + return &BufferObject{VAOID: vaoID} } diff --git a/buffers/dataType.go b/buffers/dataType.go new file mode 100755 index 0000000..6c9841f --- /dev/null +++ b/buffers/dataType.go @@ -0,0 +1,89 @@ +package buffers + +import ( + "github.com/bloeys/go-sdl-engine/logging" + "github.com/go-gl/gl/v4.6-compatibility/gl" +) + +type DataType int + +const ( + DataTypeUnknown = iota + DataTypeInt32 + DataTypeFloat32 + DataTypeFloat64 + + DataTypeVec2 + DataTypeVec3 + DataTypeVec4 +) + +type DataTypeInfo struct { + //ElementSize is size in bytes of one element (e.g. for vec3 its 4) + ElementSize int32 + //ElementCount is number of elements (e.g. for vec3 its 3) + ElementCount int32 + //ElementType is the type of each primitive (e.g. for vec3 its gl.FLOAT) + ElementType uint32 + //GLType is the type of the variable represented (e.g. for vec3 its gl.FLOAT_VEC2) + GLType uint32 +} + +//GetSize returns the total size in bytes (e.g. for vec3 its 4*3) +func (dti *DataTypeInfo) GetSize() int32 { + return dti.ElementSize * dti.ElementCount +} + +func GetDataTypeInfo(dt DataType) DataTypeInfo { + + switch dt { + case DataTypeInt32: + return DataTypeInfo{ + ElementSize: 4, + ElementCount: 1, + ElementType: gl.INT, + GLType: gl.INT, + } + + case DataTypeFloat32: + return DataTypeInfo{ + ElementSize: 4, + ElementCount: 1, + ElementType: gl.FLOAT, + GLType: gl.FLOAT, + } + case DataTypeFloat64: + return DataTypeInfo{ + ElementSize: 8, + ElementCount: 1, + ElementType: gl.DOUBLE, + GLType: gl.DOUBLE, + } + + case DataTypeVec2: + return DataTypeInfo{ + ElementSize: 4, + ElementCount: 2, + ElementType: gl.FLOAT, + GLType: gl.FLOAT_VEC2, + } + case DataTypeVec3: + return DataTypeInfo{ + ElementSize: 4, + ElementCount: 3, + ElementType: gl.FLOAT, + GLType: gl.FLOAT_VEC3, + } + case DataTypeVec4: + return DataTypeInfo{ + ElementSize: 4, + ElementCount: 4, + ElementType: gl.FLOAT, + GLType: gl.FLOAT_VEC4, + } + + default: + logging.WarnLog.Println("Unknown data type passed. DataType:", dt) + return DataTypeInfo{} + } +} diff --git a/main.go b/main.go index 46abcc7..87a93fd 100755 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ var ( window *sdl.Window simpleShader shaders.ShaderProgram + bo *buffers.BufferObject ) func main() { @@ -42,8 +43,13 @@ func main() { initOpenGL() loadShaders() + loadBuffers() - buffers.HandleBuffers(simpleShader) + simpleShader.SetAttribute("vertPos", bo, bo.VertPosBuf) + simpleShader.EnableAttribute("vertPos") + + simpleShader.SetAttribute("vertColor", bo, bo.ColorBuf) + simpleShader.EnableAttribute("vertColor") //Game loop for isRunning { @@ -99,6 +105,33 @@ func loadShaders() { simpleShader.Link() } +func loadBuffers() { + + vertices := []float32{ + -0.5, 0.5, 0, + 0.5, 0.5, 0, + -0.5, -0.5, 0, + + 0.5, 0.5, 0, + 0.5, -0.5, 0, + -0.5, -0.5, 0, + } + + colors := []float32{ + 1, 0, 0, + 0, 0, 1, + 0, 0, 1, + + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + } + + bo = buffers.NewBufferObject() + bo.GenBuffer(vertices, buffers.BufUsageStatic, buffers.BufTypeVertPos, buffers.DataTypeVec3) + bo.GenBuffer(colors, buffers.BufUsageStatic, buffers.BufTypeColor, buffers.DataTypeVec3) +} + func handleInputs() { input.EventLoopStart() @@ -125,9 +158,12 @@ func draw() { gl.Clear(gl.COLOR_BUFFER_BIT) - simpleShader.Use() + simpleShader.Activate() + //DRAW + bo.Activate() gl.DrawArrays(gl.TRIANGLES, 0, 6) + bo.Deactivate() window.GLSwap() } diff --git a/res/shaders/simple.frag.glsl b/res/shaders/simple.frag.glsl index d88aa26..5853b71 100755 --- a/res/shaders/simple.frag.glsl +++ b/res/shaders/simple.frag.glsl @@ -1,8 +1,10 @@ #version 460 +in vec3 outColor; + out vec4 fragColor; void main() { - fragColor = vec4(1, 1, 1, 1.0); + fragColor = vec4(outColor, 1.0); } diff --git a/res/shaders/simple.vert.glsl b/res/shaders/simple.vert.glsl index 9cdcfd3..d8154e4 100755 --- a/res/shaders/simple.vert.glsl +++ b/res/shaders/simple.vert.glsl @@ -1,8 +1,12 @@ #version 460 in vec3 vertPos; +in vec3 vertColor; + +out vec3 outColor; void main() { + outColor = vertColor; gl_Position = vec4(vertPos, 1.0); // vec4(vertPos.x, vertPos.y, vertPos.z, 1.0) } \ No newline at end of file diff --git a/shaders/shader_program.go b/shaders/shader_program.go index 033d57f..2632e6e 100755 --- a/shaders/shader_program.go +++ b/shaders/shader_program.go @@ -1,6 +1,7 @@ package shaders import ( + "github.com/bloeys/go-sdl-engine/buffers" "github.com/bloeys/go-sdl-engine/logging" "github.com/go-gl/gl/v4.6-compatibility/gl" ) @@ -36,12 +37,36 @@ func (sp *ShaderProgram) Link() { } } +func (sp *ShaderProgram) Activate() { + gl.UseProgram(sp.ID) +} + +func (sp *ShaderProgram) Deactivate() { + gl.UseProgram(0) +} + func (sp *ShaderProgram) GetAttribLoc(attribName string) int32 { return gl.GetAttribLocation(sp.ID, gl.Str(attribName+"\x00")) } -func (sp *ShaderProgram) Use() { - gl.UseProgram(sp.ID) +func (sp *ShaderProgram) SetAttribute(attribName string, bufObj *buffers.BufferObject, buf *buffers.Buffer) { + + bufObj.Activate() + buf.Activate() + + attribLoc := sp.GetAttribLoc(attribName) + gl.VertexAttribPointer(uint32(attribLoc), buf.ElementCount, buf.ElementType, false, buf.GetSize(), gl.PtrOffset(0)) + + bufObj.Activate() + buf.Deactivate() +} + +func (sp *ShaderProgram) EnableAttribute(attribName string) { + gl.EnableVertexAttribArray(uint32(sp.GetAttribLoc(attribName))) +} + +func (sp *ShaderProgram) DisableAttribute(attribName string) { + gl.DisableVertexAttribArray(uint32(sp.GetAttribLoc(attribName))) } func (sp *ShaderProgram) Delete() {