mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
Vertex buffer objects+vertex arrays objects+element buffer objects
This commit is contained in:
77
main.go
77
main.go
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/bloeys/go-sdl-engine/input"
|
"github.com/bloeys/go-sdl-engine/input"
|
||||||
"github.com/bloeys/go-sdl-engine/logging"
|
"github.com/bloeys/go-sdl-engine/logging"
|
||||||
@ -105,23 +107,74 @@ var simpleProg shaders.Program
|
|||||||
|
|
||||||
func loadShaders() {
|
func loadShaders() {
|
||||||
|
|
||||||
simpleVert, err := shaders.NewShaderFromFile("./res/shaders/simple.vert.glsl", shaders.Vertex)
|
simpleVert, err := shaders.NewShaderFromFile("simpleVert", "./res/shaders/simple.vert.glsl", shaders.Vertex)
|
||||||
panicIfErr(err, "Parsing vert shader failed")
|
panicIfErr(err, "Parsing vert shader failed")
|
||||||
|
|
||||||
simpleFrag, err := shaders.NewShaderFromFile("./res/shaders/simple.frag.glsl", shaders.Fragment)
|
simpleFrag, err := shaders.NewShaderFromFile("simpleFrag", "./res/shaders/simple.frag.glsl", shaders.Fragment)
|
||||||
panicIfErr(err, "Parsing frag shader failed")
|
panicIfErr(err, "Parsing frag shader failed")
|
||||||
|
|
||||||
simpleProg = shaders.NewProgram("simple")
|
simpleProg = shaders.NewProgram("simple")
|
||||||
simpleProg.AttachShader(simpleVert)
|
simpleProg.AttachShader(simpleVert)
|
||||||
simpleProg.AttachShader(simpleFrag)
|
simpleProg.AttachShader(simpleFrag)
|
||||||
|
|
||||||
simpleProg.SetUniformF32("r", 255)
|
|
||||||
|
|
||||||
simpleProg.Link()
|
simpleProg.Link()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var vao uint32
|
||||||
|
|
||||||
func gameLoop() {
|
func gameLoop() {
|
||||||
|
|
||||||
|
//vertex positions in opengl coords
|
||||||
|
verts := []float32{
|
||||||
|
-0.5, 0.5, 0,
|
||||||
|
0.5, 0.5, 0,
|
||||||
|
0.5, -0.5, 0,
|
||||||
|
-0.5, -0.5, 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Trianlge indices used for drawing
|
||||||
|
indices := []uint32{
|
||||||
|
0, 1, 2,
|
||||||
|
0, 2, 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create a VAO to store the different VBOs of a given object/set of vertices
|
||||||
|
gl.GenVertexArrays(1, &vao)
|
||||||
|
|
||||||
|
//Bind the VAO first so later buffer binds/VBOs are put within this VAO
|
||||||
|
gl.BindVertexArray(vao)
|
||||||
|
|
||||||
|
//Gen buffer to hold EBOs and fill it with data. Note that an EBO must NOT be unbound before the VAO, otherwise
|
||||||
|
//its settings are lost as the VAO records its actions
|
||||||
|
var ebo uint32
|
||||||
|
gl.GenBuffers(1, &ebo)
|
||||||
|
|
||||||
|
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
|
||||||
|
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*4, gl.Ptr(indices), gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
//Gen vertPos VBO and fill it with data
|
||||||
|
var vertPosVBO uint32
|
||||||
|
gl.GenBuffers(1, &vertPosVBO)
|
||||||
|
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, vertPosVBO)
|
||||||
|
gl.BufferData(gl.ARRAY_BUFFER, len(verts)*4, gl.Ptr(verts), gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
//Assign vertPos VBO to vertPos shader attribute by specifying that each vertPos variable
|
||||||
|
//takes 3 values from the VBO, where each value is a float.
|
||||||
|
|
||||||
|
//We also specify the total size (in bytes) of the values used for a single vertPos.
|
||||||
|
//The offset defines the bytes to skip between each set of vertPos values
|
||||||
|
vertPosLoc := uint32(gl.GetAttribLocation(simpleProg.ID, gl.Str("vertPos\x00")))
|
||||||
|
gl.VertexAttribPointer(vertPosLoc, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
|
||||||
|
|
||||||
|
//Vertex attributes are disabled by default, so we need to finally enable it
|
||||||
|
gl.EnableVertexAttribArray(vertPosLoc)
|
||||||
|
|
||||||
|
//We are done working with VBOs so can unbind the VAO to avoid corrupting it later.
|
||||||
|
//Note: Actions (binding/setting buffers, enabling/disabling attribs) done between
|
||||||
|
//bind and unbind of a VAO are recorded by it, and when its rebinded before a draw the
|
||||||
|
//settings are retrieved, therefore keep in mind work after a VAO unbind will be lost.
|
||||||
|
gl.BindVertexArray(0)
|
||||||
|
|
||||||
for isRunning {
|
for isRunning {
|
||||||
|
|
||||||
timing.FrameStarted()
|
timing.FrameStarted()
|
||||||
@ -164,6 +217,20 @@ func update() {
|
|||||||
func draw() {
|
func draw() {
|
||||||
//Clear screen and depth buffers
|
//Clear screen and depth buffers
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
|
simpleProg.Use()
|
||||||
|
|
||||||
|
deg2rad := math.Pi / 180.0
|
||||||
|
t := float64(time.Now().UnixMilli()) / 10
|
||||||
|
|
||||||
|
x := float32(math.Sin(t*deg2rad*0.3)+1) * 0.5
|
||||||
|
y := float32(math.Sin(t*deg2rad*0.5)+1) * 0.5
|
||||||
|
z := float32(math.Sin(t*deg2rad*0.7)+1) * 0.5
|
||||||
|
simpleProg.SetUniformF32("c", x, y, z)
|
||||||
|
|
||||||
|
gl.BindVertexArray(vao)
|
||||||
|
gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0))
|
||||||
|
gl.BindVertexArray(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func panicIfErr(err error, msg string) {
|
func panicIfErr(err error, msg string) {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#version 400
|
#version 460 core
|
||||||
|
|
||||||
uniform float r;
|
uniform vec3 c;
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color = vec4(r,r,r,0);
|
fragColor = vec4(c, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#version 400
|
#version 460 core
|
||||||
|
|
||||||
uniform float r;
|
in vec3 vertPos;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
gl_Position = vec4(vertPos, 1.0);
|
||||||
}
|
}
|
||||||
@ -51,10 +51,21 @@ func (p *Program) DetachShader(s Shader) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Link deletes all shaders from opengl and clears the shaders array if linking is successful.
|
||||||
|
//Note: This is allowed because only the final program is needed after linking
|
||||||
func (p *Program) Link() error {
|
func (p *Program) Link() error {
|
||||||
|
|
||||||
gl.LinkProgram(p.ID)
|
gl.LinkProgram(p.ID)
|
||||||
return getProgramLinkError(*p)
|
if err := getProgramLinkError(*p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range p.Shaders {
|
||||||
|
gl.DeleteShader(v.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Shaders = nil
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProgramLinkError(p Program) error {
|
func getProgramLinkError(p Program) error {
|
||||||
@ -89,7 +100,7 @@ func (p *Program) GetUniformLocation(name string) int32 {
|
|||||||
func (p *Program) SetUniformF32(name string, floats ...float32) bool {
|
func (p *Program) SetUniformF32(name string, floats ...float32) bool {
|
||||||
|
|
||||||
loc := p.GetUniformLocation(name)
|
loc := p.GetUniformLocation(name)
|
||||||
if loc == 0 {
|
if loc == -1 {
|
||||||
logging.WarnLog.Printf(
|
logging.WarnLog.Printf(
|
||||||
"Uniform with name '%s' was not found. "+
|
"Uniform with name '%s' was not found. "+
|
||||||
"This is either because it doesn't exist or isn't used in the shader",
|
"This is either because it doesn't exist or isn't used in the shader",
|
||||||
@ -120,7 +131,7 @@ func (p *Program) SetUniformF32(name string, floats ...float32) bool {
|
|||||||
func (p *Program) SetUniformI32(name string, ints ...int32) bool {
|
func (p *Program) SetUniformI32(name string, ints ...int32) bool {
|
||||||
|
|
||||||
loc := p.GetUniformLocation(name)
|
loc := p.GetUniformLocation(name)
|
||||||
if loc == 0 {
|
if loc == -1 {
|
||||||
logging.WarnLog.Printf(
|
logging.WarnLog.Printf(
|
||||||
"Uniform with name '%s' was not found. "+
|
"Uniform with name '%s' was not found. "+
|
||||||
"This is either because it doesn't exist or isn't used in the shader",
|
"This is either because it doesn't exist or isn't used in the shader",
|
||||||
|
|||||||
@ -10,28 +10,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
|
Name string
|
||||||
ID uint32
|
ID uint32
|
||||||
Type ShaderType
|
Type ShaderType
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewShaderFromFile reads a shader from file, creates a new opengl shader and compiles it
|
//NewShaderFromFile reads a shader from file, creates a new opengl shader and compiles it
|
||||||
func NewShaderFromFile(shaderFilePath string, st ShaderType) (Shader, error) {
|
func NewShaderFromFile(name, shaderFilePath string, st ShaderType) (Shader, error) {
|
||||||
|
|
||||||
b, err := os.ReadFile(shaderFilePath)
|
b, err := os.ReadFile(shaderFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Shader{}, err
|
return Shader{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewShaderFromString(string(b), st)
|
return NewShaderFromString(name, string(b), st)
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewShaderFromString creates a new opengl shader and compiles it
|
//NewShaderFromString creates a new opengl shader and compiles it
|
||||||
func NewShaderFromString(sourceString string, st ShaderType) (Shader, error) {
|
func NewShaderFromString(name, sourceString string, st ShaderType) (Shader, error) {
|
||||||
|
|
||||||
glString, freeFunc := gl.Strs(sourceString + "\x00")
|
glString, freeFunc := gl.Strs(sourceString + "\x00")
|
||||||
defer freeFunc()
|
defer freeFunc()
|
||||||
|
|
||||||
newShader := Shader{Type: st}
|
newShader := Shader{Name: name, Type: st}
|
||||||
if newShader.ID = gl.CreateShader(st.GLType()); newShader.ID == 0 {
|
if newShader.ID = gl.CreateShader(st.GLType()); newShader.ID == 0 {
|
||||||
logging.ErrLog.Panicln("Creating shader failed. ShaderType:", st)
|
logging.ErrLog.Panicln("Creating shader failed. ShaderType:", st)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user