mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ff1149191 | |||
| 42d99b3cc7 | |||
| 29832b9708 | |||
| 9a621d0669 | |||
| e893880f3b | |||
| cbe3d5111f | |||
| 3aa53852f3 | |||
| 46483352c7 | |||
| e38cd90a84 | |||
| 1109caef43 | |||
| e1e617e4e4 | |||
| 6dee7b0f1d |
22
.github/workflows/run-nmage.yml
vendored
Executable file
22
.github/workflows/run-nmage.yml
vendored
Executable file
@ -0,0 +1,22 @@
|
||||
name: build-nmage
|
||||
on:
|
||||
create:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-nmage-macos:
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- name: Install golang 1.17
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
- name: Install assimp-go dylib
|
||||
run: sudo mkdir -p /usr/local/lib && sudo wget https://github.com/bloeys/assimp-go/releases/download/v0.4.2/libassimp_darwin_amd64.dylib -O /usr/local/lib/libassimp.5.dylib
|
||||
- name: Install SDL2
|
||||
run: brew install sdl2{,_image,_mixer,_ttf,_gfx} pkg-config
|
||||
- name: Clone nmage
|
||||
run: git clone https://github.com/bloeys/nmage
|
||||
- name: build nmage
|
||||
working-directory: nmage
|
||||
run: go build .
|
||||
@ -1,5 +1,7 @@
|
||||
# nMage
|
||||
|
||||
[](https://github.com/bloeys/nmage/actions/workflows/run-nmage.yml)
|
||||
|
||||
nMage is a (hopefully!) high performance 3D Game Engine written in Go being developed [live](https://twitch.tv/bloeys), with recordings posted on [YouTube](https://www.youtube.com/channel/UCCf4qyNGPVwpj1HYFGahs_A).
|
||||
|
||||
This project is being built with the goals being (in no particular order):
|
||||
@ -17,6 +19,7 @@ To run the project you need:
|
||||
* A C/C++ compiler installed and in your path
|
||||
* Windows: [MingW](https://www.mingw-w64.org/downloads/#mingw-builds) or similar
|
||||
* Mac/Linux: Should be installed by default, but if not try [GCC](https://gcc.gnu.org/) or [Clang](https://releases.llvm.org/download.html)
|
||||
* Install SDL2 by following their [requirements](https://github.com/veandco/go-sdl2#requirements).
|
||||
* Get the required [assimp-go](https://github.com/bloeys/assimp-go) DLLs/DyLibs and place them correctly by following the assimp-go [README](https://github.com/bloeys/assimp-go#using-assimp-go).
|
||||
|
||||
Then you can start nMage with `go run .`
|
||||
|
||||
@ -5,14 +5,11 @@ import (
|
||||
"github.com/bloeys/nmage/logging"
|
||||
)
|
||||
|
||||
func True(check bool, msg string) {
|
||||
if consts.Debug && !check {
|
||||
logging.ErrLog.Panicln(msg)
|
||||
}
|
||||
}
|
||||
func T(check bool, msg string) {
|
||||
|
||||
func False(check bool, msg string) {
|
||||
if consts.Debug && check {
|
||||
logging.ErrLog.Panicln(msg)
|
||||
if !consts.Debug || check {
|
||||
return
|
||||
}
|
||||
|
||||
logging.ErrLog.Panicln("Assert failed:", msg)
|
||||
}
|
||||
|
||||
33
buffers/buf_usage.go
Executable file
33
buffers/buf_usage.go
Executable file
@ -0,0 +1,33 @@
|
||||
package buffers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bloeys/nmage/asserts"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
|
||||
type BufUsage int
|
||||
|
||||
const (
|
||||
//Buffer is set only once and used many times
|
||||
BufUsage_Static BufUsage = iota
|
||||
//Buffer is changed a lot and used many times
|
||||
BufUsage_Dynamic
|
||||
//Buffer is set only once and used by the GPU at most a few times
|
||||
BufUsage_Stream
|
||||
)
|
||||
|
||||
func (b BufUsage) ToGL() uint32 {
|
||||
switch b {
|
||||
case BufUsage_Static:
|
||||
return gl.STATIC_DRAW
|
||||
case BufUsage_Dynamic:
|
||||
return gl.DYNAMIC_DRAW
|
||||
case BufUsage_Stream:
|
||||
return gl.STREAM_DRAW
|
||||
}
|
||||
|
||||
asserts.T(false, fmt.Sprintf("Unexpected BufUsage value '%v'", b))
|
||||
return 0
|
||||
}
|
||||
@ -5,169 +5,85 @@ import (
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
|
||||
type BufGLType int
|
||||
|
||||
const (
|
||||
BufGLTypeUnknown BufGLType = 0
|
||||
//Generic array of data. Should be used for most data like vertex positions, vertex colors etc.
|
||||
BufGLTypeArray BufGLType = gl.ARRAY_BUFFER
|
||||
BufGLTypeIndices BufGLType = gl.ELEMENT_ARRAY_BUFFER
|
||||
)
|
||||
|
||||
type BufType int
|
||||
|
||||
const (
|
||||
BufTypeUnknown BufType = iota
|
||||
BufTypeVertPos
|
||||
BufTypeColor
|
||||
BufTypeIndex
|
||||
BufTypeNormal
|
||||
)
|
||||
|
||||
func (bt BufType) GetBufferGLType() BufGLType {
|
||||
switch bt {
|
||||
|
||||
case BufTypeNormal:
|
||||
fallthrough
|
||||
case BufTypeColor:
|
||||
fallthrough
|
||||
case BufTypeVertPos:
|
||||
return BufGLTypeArray
|
||||
|
||||
case BufTypeIndex:
|
||||
return BufGLTypeIndices
|
||||
default:
|
||||
logging.WarnLog.Println("Unknown BufferType. BufferType: ", bt)
|
||||
return BufGLTypeUnknown
|
||||
}
|
||||
}
|
||||
|
||||
type BufUsage int
|
||||
|
||||
const (
|
||||
//Buffer is set only once and used many times
|
||||
BufUsageStatic BufUsage = gl.STATIC_DRAW
|
||||
//Buffer is changed a lot and used many times
|
||||
BufUsageDynamic BufUsage = gl.DYNAMIC_DRAW
|
||||
//Buffer is set only once and used by the GPU at most a few times
|
||||
BufUsageStream BufUsage = gl.STREAM_DRAW
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
ID uint32
|
||||
Type BufType
|
||||
GLType BufGLType
|
||||
DataTypeInfo
|
||||
VAOID uint32
|
||||
//BufID is the ID of the VBO
|
||||
BufID uint32
|
||||
//IndexBufID is the ID of the index/element buffer
|
||||
IndexBufID uint32
|
||||
IndexBufCount int32
|
||||
Stride int32
|
||||
|
||||
//DataLen is the number of elements in the uploaded to the buffer
|
||||
DataLen int32
|
||||
layout []Element
|
||||
}
|
||||
|
||||
func (b *Buffer) Activate() {
|
||||
gl.BindBuffer(uint32(b.GLType), b.ID)
|
||||
func (b *Buffer) Bind() {
|
||||
gl.BindVertexArray(b.VAOID)
|
||||
}
|
||||
|
||||
func (b *Buffer) Deactivate() {
|
||||
gl.BindBuffer(uint32(b.GLType), 0)
|
||||
}
|
||||
|
||||
type BufferObject struct {
|
||||
VAOID uint32
|
||||
VertPosBuf *Buffer
|
||||
NormalBuf *Buffer
|
||||
ColorBuf *Buffer
|
||||
IndexBuf *Buffer
|
||||
}
|
||||
|
||||
func (bo *BufferObject) GenBuffer(data []float32, bufUsage BufUsage, bufType BufType, bufDataType DataType) {
|
||||
|
||||
gl.BindVertexArray(bo.VAOID)
|
||||
|
||||
//Create vertex buffer object
|
||||
var vboID uint32
|
||||
gl.GenBuffers(1, &vboID)
|
||||
if vboID == 0 {
|
||||
logging.ErrLog.Println("Failed to create openGL buffer")
|
||||
}
|
||||
|
||||
buf := &Buffer{
|
||||
ID: vboID,
|
||||
Type: bufType,
|
||||
GLType: bufType.GetBufferGLType(),
|
||||
DataTypeInfo: GetDataTypeInfo(bufDataType),
|
||||
DataLen: int32(len(data)),
|
||||
}
|
||||
bo.SetBuffer(buf)
|
||||
|
||||
//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) GenBufferUint32(data []uint32, bufUsage BufUsage, bufType BufType, bufDataType DataType) {
|
||||
|
||||
gl.BindVertexArray(bo.VAOID)
|
||||
|
||||
//Create vertex buffer object
|
||||
var vboID uint32
|
||||
gl.GenBuffers(1, &vboID)
|
||||
if vboID == 0 {
|
||||
logging.ErrLog.Println("Failed to create openGL buffer")
|
||||
}
|
||||
|
||||
buf := &Buffer{
|
||||
ID: vboID,
|
||||
Type: bufType,
|
||||
GLType: bufType.GetBufferGLType(),
|
||||
DataTypeInfo: GetDataTypeInfo(bufDataType),
|
||||
DataLen: int32(len(data)),
|
||||
}
|
||||
bo.SetBuffer(buf)
|
||||
|
||||
//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 BufTypeNormal:
|
||||
bo.NormalBuf = buf
|
||||
case BufTypeColor:
|
||||
bo.ColorBuf = buf
|
||||
case BufTypeIndex:
|
||||
bo.IndexBuf = 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() {
|
||||
func (b *Buffer) UnBind() {
|
||||
gl.BindVertexArray(0)
|
||||
}
|
||||
|
||||
func NewBufferObject() *BufferObject {
|
||||
func (b *Buffer) SetData(values []float32) {
|
||||
|
||||
var vaoID uint32
|
||||
gl.GenVertexArrays(1, &vaoID)
|
||||
if vaoID == 0 {
|
||||
gl.BindVertexArray(b.VAOID)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, b.BufID)
|
||||
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(values)*4, gl.Ptr(values), BufUsage_Static.ToGL())
|
||||
|
||||
gl.BindVertexArray(0)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
}
|
||||
|
||||
func (b *Buffer) SetIndexBufData(values []uint32) {
|
||||
|
||||
b.IndexBufCount = int32(len(values))
|
||||
gl.BindVertexArray(b.VAOID)
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b.IndexBufID)
|
||||
|
||||
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(values)*4, gl.Ptr(values), BufUsage_Static.ToGL())
|
||||
|
||||
gl.BindVertexArray(0)
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
|
||||
}
|
||||
|
||||
func (b *Buffer) GetLayout() []Element {
|
||||
e := make([]Element, len(b.layout))
|
||||
copy(e, b.layout)
|
||||
return e
|
||||
}
|
||||
|
||||
func (b *Buffer) SetLayout(layout ...Element) {
|
||||
|
||||
b.layout = layout
|
||||
|
||||
b.Stride = 0
|
||||
for i := 0; i < len(b.layout); i++ {
|
||||
|
||||
b.layout[i].Offset = int(b.Stride)
|
||||
b.Stride += b.layout[i].Size()
|
||||
}
|
||||
}
|
||||
|
||||
func NewBuffer(layout ...Element) Buffer {
|
||||
|
||||
b := Buffer{}
|
||||
gl.GenVertexArrays(1, &b.VAOID)
|
||||
if b.VAOID == 0 {
|
||||
logging.ErrLog.Println("Failed to create openGL vertex array object")
|
||||
}
|
||||
|
||||
return &BufferObject{VAOID: vaoID}
|
||||
gl.GenBuffers(1, &b.BufID)
|
||||
if b.BufID == 0 {
|
||||
logging.ErrLog.Println("Failed to create openGL buffer")
|
||||
}
|
||||
|
||||
gl.GenBuffers(1, &b.IndexBufID)
|
||||
if b.IndexBufID == 0 {
|
||||
logging.ErrLog.Println("Failed to create openGL buffer")
|
||||
}
|
||||
|
||||
b.SetLayout(layout...)
|
||||
return b
|
||||
}
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
package buffers
|
||||
|
||||
import (
|
||||
"github.com/bloeys/nmage/logging"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
|
||||
type DataType int
|
||||
|
||||
const (
|
||||
DataTypeUnknown DataType = iota
|
||||
DataTypeUint32
|
||||
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 DataTypeUint32:
|
||||
fallthrough
|
||||
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{}
|
||||
}
|
||||
}
|
||||
122
buffers/element.go
Executable file
122
buffers/element.go
Executable file
@ -0,0 +1,122 @@
|
||||
package buffers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bloeys/nmage/asserts"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
|
||||
//Element represents an element that makes up a buffer (e.g. Vec3 at an offset of 12 bytes)
|
||||
type Element struct {
|
||||
Offset int
|
||||
ElementType
|
||||
}
|
||||
|
||||
//ElementType is the type of an element thats makes up a buffer (e.g. Vec3)
|
||||
type ElementType int
|
||||
|
||||
const (
|
||||
DataTypeUnknown ElementType = iota
|
||||
DataTypeUint32
|
||||
DataTypeInt32
|
||||
DataTypeFloat32
|
||||
|
||||
DataTypeVec2
|
||||
DataTypeVec3
|
||||
DataTypeVec4
|
||||
)
|
||||
|
||||
func (dt ElementType) GLType() uint32 {
|
||||
|
||||
switch dt {
|
||||
case DataTypeUint32:
|
||||
return gl.UNSIGNED_INT
|
||||
case DataTypeInt32:
|
||||
return gl.INT
|
||||
|
||||
case DataTypeFloat32:
|
||||
fallthrough
|
||||
case DataTypeVec2:
|
||||
fallthrough
|
||||
case DataTypeVec3:
|
||||
fallthrough
|
||||
case DataTypeVec4:
|
||||
return gl.FLOAT
|
||||
|
||||
default:
|
||||
asserts.T(false, fmt.Sprintf("Unknown data type passed. DataType '%v'", dt))
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//CompSize returns the size in bytes for one component of the type (e.g. for Vec2 its 4)
|
||||
func (dt ElementType) CompSize() int32 {
|
||||
|
||||
switch dt {
|
||||
case DataTypeUint32:
|
||||
fallthrough
|
||||
case DataTypeFloat32:
|
||||
fallthrough
|
||||
case DataTypeInt32:
|
||||
fallthrough
|
||||
case DataTypeVec2:
|
||||
fallthrough
|
||||
case DataTypeVec3:
|
||||
fallthrough
|
||||
case DataTypeVec4:
|
||||
return 4
|
||||
|
||||
default:
|
||||
asserts.T(false, fmt.Sprintf("Unknown data type passed. DataType '%v'", dt))
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//CompCount returns the number of components in the element (e.g. for Vec2 its 2)
|
||||
func (dt ElementType) CompCount() int32 {
|
||||
|
||||
switch dt {
|
||||
case DataTypeUint32:
|
||||
fallthrough
|
||||
case DataTypeFloat32:
|
||||
fallthrough
|
||||
case DataTypeInt32:
|
||||
return 1
|
||||
|
||||
case DataTypeVec2:
|
||||
return 2
|
||||
case DataTypeVec3:
|
||||
return 3
|
||||
case DataTypeVec4:
|
||||
return 4
|
||||
|
||||
default:
|
||||
asserts.T(false, fmt.Sprintf("Unknown data type passed. DataType '%v'", dt))
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//Size returns the total size in bytes (e.g. for vec3 its 3*4=12 bytes)
|
||||
func (dt ElementType) Size() int32 {
|
||||
|
||||
switch dt {
|
||||
case DataTypeUint32:
|
||||
fallthrough
|
||||
case DataTypeFloat32:
|
||||
fallthrough
|
||||
case DataTypeInt32:
|
||||
return 4
|
||||
|
||||
case DataTypeVec2:
|
||||
return 2 * 4
|
||||
case DataTypeVec3:
|
||||
return 3 * 4
|
||||
case DataTypeVec4:
|
||||
return 4 * 4
|
||||
|
||||
default:
|
||||
asserts.T(false, fmt.Sprintf("Unknown data type passed. DataType '%v'", dt))
|
||||
return 0
|
||||
}
|
||||
}
|
||||
107
engine/engine.go
Executable file
107
engine/engine.go
Executable file
@ -0,0 +1,107 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"github.com/bloeys/nmage/timing"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
type Window struct {
|
||||
SDLWin *sdl.Window
|
||||
GlCtx sdl.GLContext
|
||||
}
|
||||
|
||||
func (w *Window) Destroy() error {
|
||||
return w.SDLWin.Destroy()
|
||||
}
|
||||
|
||||
func Init() error {
|
||||
|
||||
timing.Init()
|
||||
err := initSDL()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func initSDL() error {
|
||||
|
||||
err := sdl.Init(sdl.INIT_EVERYTHING)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sdl.ShowCursor(1)
|
||||
|
||||
sdl.GLSetAttribute(sdl.MAJOR_VERSION, 4)
|
||||
sdl.GLSetAttribute(sdl.MINOR_VERSION, 1)
|
||||
|
||||
// R(0-255) G(0-255) B(0-255)
|
||||
sdl.GLSetAttribute(sdl.GL_RED_SIZE, 8)
|
||||
sdl.GLSetAttribute(sdl.GL_GREEN_SIZE, 8)
|
||||
sdl.GLSetAttribute(sdl.GL_BLUE_SIZE, 8)
|
||||
|
||||
sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1)
|
||||
sdl.GLSetAttribute(sdl.GL_DEPTH_SIZE, 24)
|
||||
sdl.GLSetAttribute(sdl.GL_STENCIL_SIZE, 8)
|
||||
|
||||
sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateOpenGLWindow(title string, x, y, width, height int32, flags WindowFlags) (*Window, error) {
|
||||
return createWindow(title, x, y, width, height, WindowFlags_OPENGL|flags)
|
||||
}
|
||||
|
||||
func CreateOpenGLWindowCentered(title string, width, height int32, flags WindowFlags) (*Window, error) {
|
||||
return createWindow(title, -1, -1, width, height, WindowFlags_OPENGL|flags)
|
||||
}
|
||||
|
||||
func createWindow(title string, x, y, width, height int32, flags WindowFlags) (*Window, error) {
|
||||
|
||||
if x == -1 && y == -1 {
|
||||
x = sdl.WINDOWPOS_CENTERED
|
||||
y = sdl.WINDOWPOS_CENTERED
|
||||
}
|
||||
|
||||
sdlWin, err := sdl.CreateWindow(title, x, y, width, height, uint32(flags))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
win := &Window{SDLWin: sdlWin}
|
||||
|
||||
win.GlCtx, err = sdlWin.GLCreateContext()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = initOpenGL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return win, err
|
||||
}
|
||||
|
||||
func initOpenGL() error {
|
||||
|
||||
if err := gl.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.CullFace(gl.BACK)
|
||||
gl.FrontFace(gl.CCW)
|
||||
|
||||
gl.ClearColor(0, 0, 0, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetVSync(enabled bool) {
|
||||
if enabled {
|
||||
sdl.GLSetSwapInterval(1)
|
||||
} else {
|
||||
sdl.GLSetSwapInterval(0)
|
||||
}
|
||||
}
|
||||
29
engine/windowflags.go
Executable file
29
engine/windowflags.go
Executable file
@ -0,0 +1,29 @@
|
||||
package engine
|
||||
|
||||
import "github.com/veandco/go-sdl2/sdl"
|
||||
|
||||
type WindowFlags int
|
||||
|
||||
const (
|
||||
WindowFlags_FULLSCREEN WindowFlags = sdl.WINDOW_FULLSCREEN
|
||||
WindowFlags_OPENGL WindowFlags = sdl.WINDOW_OPENGL
|
||||
WindowFlags_SHOWN WindowFlags = sdl.WINDOW_SHOWN
|
||||
WindowFlags_HIDDEN WindowFlags = sdl.WINDOW_HIDDEN
|
||||
WindowFlags_BORDERLESS WindowFlags = sdl.WINDOW_BORDERLESS
|
||||
WindowFlags_RESIZABLE WindowFlags = sdl.WINDOW_RESIZABLE
|
||||
WindowFlags_MINIMIZED WindowFlags = sdl.WINDOW_MINIMIZED
|
||||
WindowFlags_MAXIMIZED WindowFlags = sdl.WINDOW_MAXIMIZED
|
||||
WindowFlags_INPUT_GRABBED WindowFlags = sdl.WINDOW_INPUT_GRABBED
|
||||
WindowFlags_INPUT_FOCUS WindowFlags = sdl.WINDOW_INPUT_FOCUS
|
||||
WindowFlags_MOUSE_FOCUS WindowFlags = sdl.WINDOW_MOUSE_FOCUS
|
||||
WindowFlags_FULLSCREEN_DESKTOP WindowFlags = sdl.WINDOW_FULLSCREEN_DESKTOP
|
||||
WindowFlags_FOREIGN WindowFlags = sdl.WINDOW_FOREIGN
|
||||
WindowFlags_ALLOW_HIGHDPI WindowFlags = sdl.WINDOW_ALLOW_HIGHDPI
|
||||
WindowFlags_MOUSE_CAPTURE WindowFlags = sdl.WINDOW_MOUSE_CAPTURE
|
||||
WindowFlags_ALWAYS_ON_TOP WindowFlags = sdl.WINDOW_ALWAYS_ON_TOP
|
||||
WindowFlags_SKIP_TASKBAR WindowFlags = sdl.WINDOW_SKIP_TASKBAR
|
||||
WindowFlags_UTILITY WindowFlags = sdl.WINDOW_UTILITY
|
||||
WindowFlags_TOOLTIP WindowFlags = sdl.WINDOW_TOOLTIP
|
||||
WindowFlags_POPUP_MENU WindowFlags = sdl.WINDOW_POPUP_MENU
|
||||
// WindowFlags_VULKAN WindowFlags = sdl.WINDOW_VULKAN
|
||||
)
|
||||
2
go.mod
2
go.mod
@ -7,7 +7,7 @@ require github.com/veandco/go-sdl2 v0.4.10
|
||||
require github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784
|
||||
|
||||
require (
|
||||
github.com/bloeys/assimp-go v0.3.3
|
||||
github.com/bloeys/assimp-go v0.4.2
|
||||
github.com/bloeys/gglm v0.3.1
|
||||
github.com/inkyblackness/imgui-go/v4 v4.3.0
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@ -1,9 +1,5 @@
|
||||
github.com/bloeys/assimp-go v0.3.1 h1:GANPXH8ER/4B/XsxZOw03GLZi2qKiWapSJ9dntrGoic=
|
||||
github.com/bloeys/assimp-go v0.3.1/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
|
||||
github.com/bloeys/assimp-go v0.3.2 h1:CsKnLloWZyn6uYNNaQE2Jq2Q+yH4d71A+CxbpU2flng=
|
||||
github.com/bloeys/assimp-go v0.3.2/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
|
||||
github.com/bloeys/assimp-go v0.3.3 h1:36Cqdsv/vVWg7mx6Kvu++1Z0SftdAQF4a+ApllpVT4M=
|
||||
github.com/bloeys/assimp-go v0.3.3/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
|
||||
github.com/bloeys/assimp-go v0.4.2 h1:ArVK74BCFcTO/rCGj2NgZG9xtbjnJdEn5npIeJx1Z04=
|
||||
github.com/bloeys/assimp-go v0.4.2/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
|
||||
github.com/bloeys/gglm v0.3.1 h1:Sy9upW7SBsBfDXrSmEhid3aQ+7J7itej+upwcxOnPMQ=
|
||||
github.com/bloeys/gglm v0.3.1/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
|
||||
315
main.go
315
main.go
@ -6,28 +6,31 @@ import (
|
||||
|
||||
"github.com/bloeys/assimp-go/asig"
|
||||
"github.com/bloeys/gglm/gglm"
|
||||
"github.com/bloeys/nmage/asserts"
|
||||
"github.com/bloeys/nmage/buffers"
|
||||
"github.com/bloeys/nmage/engine"
|
||||
"github.com/bloeys/nmage/input"
|
||||
"github.com/bloeys/nmage/logging"
|
||||
"github.com/bloeys/nmage/shaders"
|
||||
"github.com/bloeys/nmage/materials"
|
||||
"github.com/bloeys/nmage/meshes"
|
||||
"github.com/bloeys/nmage/timing"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
"github.com/inkyblackness/imgui-go/v4"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
//TODO:
|
||||
//Make a window/engine class
|
||||
//Mesh class
|
||||
//TODO: Tasks:
|
||||
//Engine loop
|
||||
//Proper rendering setup
|
||||
//Flesh out the material system
|
||||
//Object
|
||||
//Abstract UI
|
||||
//Textures
|
||||
//Proper Asset loading
|
||||
//Rework buffers package
|
||||
//Interleaved or packed buffers (xyzxyzxyz OR xxxyyyzzz)
|
||||
//Audio
|
||||
|
||||
//Low Priority:
|
||||
// Proper Asset loading
|
||||
// Rework buffers package
|
||||
// Interleaved or packed buffers (xyzxyzxyz OR xxxyyyzzz)
|
||||
|
||||
type ImguiInfo struct {
|
||||
imCtx *imgui.Context
|
||||
|
||||
@ -42,11 +45,11 @@ var (
|
||||
winHeight int32 = 720
|
||||
|
||||
isRunning bool = true
|
||||
window *sdl.Window
|
||||
window *engine.Window
|
||||
|
||||
simpleShader shaders.ShaderProgram
|
||||
imShader shaders.ShaderProgram
|
||||
bo *buffers.BufferObject
|
||||
simpleMat *materials.Material
|
||||
imguiMat *materials.Material
|
||||
cubeMesh *meshes.Mesh
|
||||
|
||||
modelMat = gglm.NewTrMatId()
|
||||
projMat = &gglm.Mat4{}
|
||||
@ -61,44 +64,35 @@ func main() {
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
||||
err := initSDL()
|
||||
//Init engine
|
||||
err := engine.Init()
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to init SDL. Err:", err)
|
||||
logging.ErrLog.Fatalln("Failed to init nMage. Err:", err)
|
||||
}
|
||||
|
||||
window, err = sdl.CreateWindow("Go SDL Engine", sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, winWidth, winHeight, sdl.WINDOW_OPENGL|sdl.WINDOW_RESIZABLE)
|
||||
//Create window
|
||||
window, err = engine.CreateOpenGLWindowCentered("nMage", winWidth, winHeight, engine.WindowFlags_RESIZABLE)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create window. Err: ", err)
|
||||
}
|
||||
defer window.Destroy()
|
||||
|
||||
glCtx, err := window.GLCreateContext()
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create OpenGL context. Err: ", err)
|
||||
}
|
||||
defer sdl.GLDeleteContext(glCtx)
|
||||
engine.SetVSync(false)
|
||||
|
||||
err = initOpenGL()
|
||||
//Create materials
|
||||
simpleMat = materials.NewMaterial("Simple Mat", "./res/shaders/simple")
|
||||
imguiMat = materials.NewMaterial("ImGUI Mat", "./res/shaders/imgui")
|
||||
|
||||
//Load meshes
|
||||
cubeMesh, err = meshes.NewMesh("Cube", "./res/models/color-cube.fbx", asig.PostProcess(0))
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln(err)
|
||||
logging.ErrLog.Fatalln("Failed to load cube mesh. Err: ", err)
|
||||
}
|
||||
|
||||
//Set vsync
|
||||
sdl.GLSetSwapInterval(0)
|
||||
|
||||
loadShaders()
|
||||
loadBuffers()
|
||||
initImGUI()
|
||||
|
||||
//Enable vertex attributes
|
||||
simpleShader.SetAttribute("vertPosIn", bo, bo.VertPosBuf)
|
||||
simpleShader.EnableAttribute("vertPosIn")
|
||||
|
||||
simpleShader.SetAttribute("vertColorIn", bo, bo.ColorBuf)
|
||||
simpleShader.EnableAttribute("vertColorIn")
|
||||
|
||||
simpleShader.SetAttribute("vertNormalIn", bo, bo.NormalBuf)
|
||||
simpleShader.EnableAttribute("vertNormalIn")
|
||||
simpleMat.SetAttribute(cubeMesh.Buf)
|
||||
|
||||
//Movement, scale and rotation
|
||||
translationMat := gglm.NewTranslationMat(gglm.NewVec3(0, 0, 0))
|
||||
@ -106,21 +100,20 @@ func main() {
|
||||
rotMat := gglm.NewRotMat(gglm.NewQuatEuler(gglm.NewVec3(0, 0, 0).AsRad()))
|
||||
|
||||
modelMat.Mul(translationMat.Mul(rotMat.Mul(scaleMat)))
|
||||
simpleShader.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
simpleMat.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
|
||||
//Moves objects into the cameras view
|
||||
updateViewMat()
|
||||
|
||||
//Perspective/Depth
|
||||
projMat := gglm.Perspective(45*gglm.Deg2Rad, float32(winWidth)/float32(winHeight), 0.1, 500)
|
||||
simpleShader.SetUnifMat4("projMat", projMat)
|
||||
simpleMat.SetUnifMat4("projMat", projMat)
|
||||
|
||||
//Lights
|
||||
simpleShader.SetUnifVec3("lightPos1", &lightPos1)
|
||||
simpleShader.SetUnifVec3("lightColor1", &lightColor1)
|
||||
simpleMat.SetUnifVec3("lightPos1", &lightPos1)
|
||||
simpleMat.SetUnifVec3("lightColor1", &lightColor1)
|
||||
|
||||
//Game loop
|
||||
timing.Init()
|
||||
for isRunning {
|
||||
|
||||
timing.FrameStarted()
|
||||
@ -132,154 +125,14 @@ func main() {
|
||||
|
||||
timing.FrameEnded()
|
||||
|
||||
window.SetTitle(fmt.Sprintf("FPS: %.0f; Elapsed: %v", 1/timing.DT(), timing.ElapsedTime()))
|
||||
window.SDLWin.SetTitle(fmt.Sprintf("FPS: %.0f; Elapsed: %v", 1/timing.DT(), timing.ElapsedTime()))
|
||||
}
|
||||
}
|
||||
|
||||
func updateViewMat() {
|
||||
targetPos := camPos.Clone().Add(camForward)
|
||||
viewMat := gglm.LookAt(camPos, targetPos, gglm.NewVec3(0, 1, 0))
|
||||
simpleShader.SetUnifMat4("viewMat", &viewMat.Mat4)
|
||||
}
|
||||
|
||||
func initSDL() error {
|
||||
|
||||
err := sdl.Init(sdl.INIT_EVERYTHING)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sdl.ShowCursor(1)
|
||||
|
||||
sdl.GLSetAttribute(sdl.MAJOR_VERSION, 4)
|
||||
sdl.GLSetAttribute(sdl.MINOR_VERSION, 1)
|
||||
|
||||
// R(0-255) G(0-255) B(0-255)
|
||||
sdl.GLSetAttribute(sdl.GL_RED_SIZE, 8)
|
||||
sdl.GLSetAttribute(sdl.GL_GREEN_SIZE, 8)
|
||||
sdl.GLSetAttribute(sdl.GL_BLUE_SIZE, 8)
|
||||
|
||||
sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1)
|
||||
sdl.GLSetAttribute(sdl.GL_DEPTH_SIZE, 24)
|
||||
sdl.GLSetAttribute(sdl.GL_STENCIL_SIZE, 8)
|
||||
|
||||
sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initOpenGL() error {
|
||||
|
||||
if err := gl.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.CullFace(gl.BACK)
|
||||
gl.FrontFace(gl.CCW)
|
||||
|
||||
gl.ClearColor(0, 0, 0, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadShaders() {
|
||||
|
||||
var err error
|
||||
simpleShader, err = shaders.NewShaderProgram()
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader program. Err: ", err)
|
||||
}
|
||||
|
||||
vertShader, err := shaders.LoadAndCompilerShader("./res/shaders/simple.vert.glsl", shaders.VertexShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err)
|
||||
}
|
||||
|
||||
fragShader, err := shaders.LoadAndCompilerShader("./res/shaders/simple.frag.glsl", shaders.FragmentShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err)
|
||||
}
|
||||
|
||||
simpleShader.AttachShader(vertShader)
|
||||
simpleShader.AttachShader(fragShader)
|
||||
simpleShader.Link()
|
||||
|
||||
//ImGUI shader
|
||||
imShader, err = shaders.NewShaderProgram()
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader program. Err: ", err)
|
||||
}
|
||||
|
||||
imguiVertShader, err := shaders.LoadAndCompilerShader("./res/shaders/imgui.vert.glsl", shaders.VertexShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err)
|
||||
}
|
||||
|
||||
imguiFragShader, err := shaders.LoadAndCompilerShader("./res/shaders/imgui.frag.glsl", shaders.FragmentShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err)
|
||||
}
|
||||
|
||||
imShader.AttachShader(imguiVertShader)
|
||||
imShader.AttachShader(imguiFragShader)
|
||||
imShader.Link()
|
||||
}
|
||||
|
||||
func flattenVec3(vec3s []gglm.Vec3) []float32 {
|
||||
|
||||
floats := make([]float32, len(vec3s)*3)
|
||||
for i := 0; i < len(vec3s); i++ {
|
||||
floats[i*3+0] = vec3s[i].X()
|
||||
floats[i*3+1] = vec3s[i].Y()
|
||||
floats[i*3+2] = vec3s[i].Z()
|
||||
}
|
||||
|
||||
return floats
|
||||
}
|
||||
|
||||
func flattenVec4(vec4s []gglm.Vec4) []float32 {
|
||||
|
||||
floats := make([]float32, len(vec4s)*4)
|
||||
for i := 0; i < len(vec4s); i++ {
|
||||
floats[i*4+0] = vec4s[i].X()
|
||||
floats[i*4+1] = vec4s[i].Y()
|
||||
floats[i*4+2] = vec4s[i].Z()
|
||||
floats[i*4+3] = vec4s[i].W()
|
||||
}
|
||||
|
||||
return floats
|
||||
}
|
||||
|
||||
func flattenFaces(faces []asig.Face) []uint32 {
|
||||
|
||||
asserts.True(len(faces[0].Indices) == 3, fmt.Sprintf("Face doesn't have 3 indices. Index count: %v\n", len(faces[0].Indices)))
|
||||
|
||||
uints := make([]uint32, len(faces)*3)
|
||||
for i := 0; i < len(faces); i++ {
|
||||
uints[i*3+0] = uint32(faces[i].Indices[0])
|
||||
uints[i*3+1] = uint32(faces[i].Indices[1])
|
||||
uints[i*3+2] = uint32(faces[i].Indices[2])
|
||||
}
|
||||
|
||||
return uints
|
||||
}
|
||||
|
||||
func loadBuffers() {
|
||||
|
||||
// scene, release, err := asig.ImportFile("./res/models/weird-cube.fbx", asig.PostProcessTriangulate)
|
||||
scene, release, err := asig.ImportFile("./res/models/color-cube.fbx", asig.PostProcessTriangulate)
|
||||
if err != nil {
|
||||
logging.ErrLog.Panicln("Failed to load model. Err: " + err.Error())
|
||||
}
|
||||
release()
|
||||
|
||||
bo = buffers.NewBufferObject()
|
||||
bo.GenBuffer(flattenVec3(scene.Meshes[0].Vertices), buffers.BufUsageStatic, buffers.BufTypeVertPos, buffers.DataTypeVec3)
|
||||
bo.GenBuffer(flattenVec3(scene.Meshes[0].Normals), buffers.BufUsageStatic, buffers.BufTypeNormal, buffers.DataTypeVec3)
|
||||
bo.GenBuffer(flattenVec4(scene.Meshes[0].ColorSets[0]), buffers.BufUsageStatic, buffers.BufTypeColor, buffers.DataTypeVec4)
|
||||
bo.GenBufferUint32(flattenFaces(scene.Meshes[0].Faces), buffers.BufUsageStatic, buffers.BufTypeIndex, buffers.DataTypeUint32)
|
||||
simpleMat.SetUnifMat4("viewMat", &viewMat.Mat4)
|
||||
}
|
||||
|
||||
func initImGUI() {
|
||||
@ -309,11 +162,11 @@ func initImGUI() {
|
||||
imIO.Fonts().SetTextureID(imgui.TextureID(imguiInfo.texID))
|
||||
|
||||
//Shader attributes
|
||||
imShader.Activate()
|
||||
imShader.EnableAttribute("Position")
|
||||
imShader.EnableAttribute("UV")
|
||||
imShader.EnableAttribute("Color")
|
||||
imShader.Deactivate()
|
||||
imguiMat.Bind()
|
||||
imguiMat.EnableAttribute("Position")
|
||||
imguiMat.EnableAttribute("UV")
|
||||
imguiMat.EnableAttribute("Color")
|
||||
imguiMat.UnBind()
|
||||
|
||||
//Init imgui input mapping
|
||||
keys := map[int]int{
|
||||
@ -380,26 +233,12 @@ func handleInputs() {
|
||||
case *sdl.MouseMotionEvent:
|
||||
input.HandleMouseMotionEvent(e)
|
||||
|
||||
case *sdl.WindowEvent:
|
||||
|
||||
//NOTE: SDL is not firing window resize, but is resizing the window by itself
|
||||
// if e.Type != sdl.WINDOWEVENT_SIZE_CHANGED {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// winWidth = e.Data1
|
||||
// winHeight = e.Data2
|
||||
// window.SetSize(int32(winWidth), int32(winHeight))
|
||||
|
||||
// projMat = gglm.Perspective(45*gglm.Deg2Rad, float32(winWidth)/float32(winHeight), 0.1, 20)
|
||||
// simpleShader.SetUnifMat4("projMat", projMat)
|
||||
|
||||
case *sdl.QuitEvent:
|
||||
isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
currWinWidth, currWinHeight := window.GetSize()
|
||||
currWinWidth, currWinHeight := window.SDLWin.GetSize()
|
||||
if winWidth != currWinWidth || winHeight != currWinHeight {
|
||||
handleWindowResize(currWinWidth, currWinHeight)
|
||||
}
|
||||
@ -422,14 +261,14 @@ func handleWindowResize(newWinWidth, newWinHeight int32) {
|
||||
winWidth = newWinWidth
|
||||
winHeight = newWinHeight
|
||||
|
||||
fbWidth, fbHeight := window.GLGetDrawableSize()
|
||||
fbWidth, fbHeight := window.SDLWin.GLGetDrawableSize()
|
||||
if fbWidth <= 0 || fbHeight <= 0 {
|
||||
return
|
||||
}
|
||||
gl.Viewport(0, 0, fbWidth, fbHeight)
|
||||
|
||||
projMat = gglm.Perspective(45*gglm.Deg2Rad, float32(winWidth)/float32(winHeight), 0.1, 20)
|
||||
simpleShader.SetUnifMat4("projMat", projMat)
|
||||
simpleMat.SetUnifMat4("projMat", projMat)
|
||||
}
|
||||
|
||||
var time uint64 = 0
|
||||
@ -443,7 +282,7 @@ var lightColor1 gglm.Vec3 = *gglm.NewVec3(1, 1, 1)
|
||||
|
||||
func runGameLogic() {
|
||||
|
||||
var camSpeed float32 = 15.0
|
||||
var camSpeed float32 = 15
|
||||
if input.KeyDown(sdl.K_w) {
|
||||
camPos.Data[1] += camSpeed * timing.DT()
|
||||
updateViewMat()
|
||||
@ -470,7 +309,7 @@ func runGameLogic() {
|
||||
}
|
||||
|
||||
modelMat.Rotate(10*timing.DT()*gglm.Deg2Rad, gglm.NewVec3(1, 1, 1).Normalize())
|
||||
simpleShader.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
simpleMat.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
|
||||
//ImGUI
|
||||
imIO := imgui.CurrentIO()
|
||||
@ -489,19 +328,19 @@ func runGameLogic() {
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.SliderFloat3("Ambient Color", &ambientColor.Data, 0, 1) {
|
||||
simpleShader.SetUnifVec3("ambientLightColor", &ambientColor)
|
||||
simpleMat.SetUnifVec3("ambientLightColor", &ambientColor)
|
||||
}
|
||||
|
||||
if imgui.SliderFloat("Ambient Color Strength", &ambientColorStrength, 0, 1) {
|
||||
simpleShader.SetUnifFloat32("ambientStrength", ambientColorStrength)
|
||||
simpleMat.SetUnifFloat32("ambientStrength", ambientColorStrength)
|
||||
}
|
||||
|
||||
if imgui.SliderFloat3("Light Pos 1", &lightPos1.Data, -10, 10) {
|
||||
simpleShader.SetUnifVec3("lightPos1", &lightPos1)
|
||||
simpleMat.SetUnifVec3("lightPos1", &lightPos1)
|
||||
}
|
||||
|
||||
if imgui.SliderFloat3("Light Color 1", &lightColor1.Data, 0, 1) {
|
||||
simpleShader.SetUnifVec3("lightColor1", &lightColor1)
|
||||
simpleMat.SetUnifVec3("lightColor1", &lightColor1)
|
||||
}
|
||||
|
||||
imgui.Render()
|
||||
@ -509,38 +348,29 @@ func runGameLogic() {
|
||||
|
||||
func draw() {
|
||||
|
||||
gl.Disable(gl.SCISSOR_TEST)
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
|
||||
simpleShader.Activate()
|
||||
|
||||
//DRAW
|
||||
bo.Activate()
|
||||
simpleMat.Bind()
|
||||
cubeMesh.Buf.Bind()
|
||||
tempModelMat := modelMat.Clone()
|
||||
|
||||
rowSize := 10
|
||||
rowSize := 100
|
||||
for y := 0; y < rowSize; y++ {
|
||||
for x := 0; x < rowSize; x++ {
|
||||
simpleShader.SetUnifMat4("modelMat", &tempModelMat.Translate(gglm.NewVec3(-1, 0, 0)).Mat4)
|
||||
gl.DrawElements(gl.TRIANGLES, int32(bo.IndexBuf.DataLen), gl.UNSIGNED_INT, gl.PtrOffset(0))
|
||||
simpleMat.SetUnifMat4("modelMat", &tempModelMat.Translate(gglm.NewVec3(-1, 0, 0)).Mat4)
|
||||
gl.DrawElements(gl.TRIANGLES, cubeMesh.Buf.IndexBufCount, gl.UNSIGNED_INT, gl.PtrOffset(0))
|
||||
}
|
||||
simpleShader.SetUnifMat4("modelMat", &tempModelMat.Translate(gglm.NewVec3(float32(rowSize), -1, 0)).Mat4)
|
||||
simpleMat.SetUnifMat4("modelMat", &tempModelMat.Translate(gglm.NewVec3(float32(rowSize), -1, 0)).Mat4)
|
||||
}
|
||||
|
||||
simpleShader.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
bo.Deactivate()
|
||||
|
||||
drawUI()
|
||||
|
||||
window.GLSwap()
|
||||
simpleMat.SetUnifMat4("modelMat", &modelMat.Mat4)
|
||||
window.SDLWin.GLSwap()
|
||||
}
|
||||
|
||||
func drawUI() {
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
fbWidth, fbHeight := window.GLGetDrawableSize()
|
||||
fbWidth, fbHeight := window.SDLWin.GLGetDrawableSize()
|
||||
if fbWidth <= 0 || fbHeight <= 0 {
|
||||
return
|
||||
}
|
||||
@ -564,13 +394,13 @@ func drawUI() {
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
|
||||
// DisplayMin is typically (0,0) for single viewport apps.
|
||||
|
||||
imShader.Activate()
|
||||
imguiMat.Bind()
|
||||
|
||||
gl.Uniform1i(gl.GetUniformLocation(imShader.ID, gl.Str("Texture\x00")), 0)
|
||||
gl.Uniform1i(gl.GetUniformLocation(imguiMat.ShaderProg.ID, gl.Str("Texture\x00")), 0)
|
||||
|
||||
//PERF: only update the ortho matrix on window resize
|
||||
orthoMat := gglm.Ortho(0, float32(winWidth), 0, float32(winHeight), 0, 20)
|
||||
imShader.SetUnifMat4("ProjMtx", &orthoMat.Mat4)
|
||||
imguiMat.SetUnifMat4("ProjMtx", &orthoMat.Mat4)
|
||||
gl.BindSampler(0, 0) // Rely on combined texture/sampler state.
|
||||
|
||||
// Recreate the VAO every time
|
||||
@ -580,12 +410,12 @@ func drawUI() {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, imguiInfo.vboID)
|
||||
|
||||
vertexSize, vertexOffsetPos, vertexOffsetUv, vertexOffsetCol := imgui.VertexBufferLayout()
|
||||
imShader.EnableAttribute("Position")
|
||||
imShader.EnableAttribute("UV")
|
||||
imShader.EnableAttribute("Color")
|
||||
gl.VertexAttribPointerWithOffset(uint32(imShader.GetAttribLoc("Position")), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetPos))
|
||||
gl.VertexAttribPointerWithOffset(uint32(imShader.GetAttribLoc("UV")), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetUv))
|
||||
gl.VertexAttribPointerWithOffset(uint32(imShader.GetAttribLoc("Color")), 4, gl.UNSIGNED_BYTE, true, int32(vertexSize), uintptr(vertexOffsetCol))
|
||||
imguiMat.EnableAttribute("Position")
|
||||
imguiMat.EnableAttribute("UV")
|
||||
imguiMat.EnableAttribute("Color")
|
||||
gl.VertexAttribPointerWithOffset(uint32(imguiMat.GetAttribLoc("Position")), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetPos))
|
||||
gl.VertexAttribPointerWithOffset(uint32(imguiMat.GetAttribLoc("UV")), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetUv))
|
||||
gl.VertexAttribPointerWithOffset(uint32(imguiMat.GetAttribLoc("Color")), 4, gl.UNSIGNED_BYTE, true, int32(vertexSize), uintptr(vertexOffsetCol))
|
||||
|
||||
indexSize := imgui.IndexBufferLayout()
|
||||
drawType := gl.UNSIGNED_SHORT
|
||||
@ -610,7 +440,6 @@ func drawUI() {
|
||||
} else {
|
||||
|
||||
gl.BindTexture(gl.TEXTURE_2D, imguiInfo.texID)
|
||||
// gl.BindTexture(gl.TEXTURE_2D, uint32(cmd.TextureID()))
|
||||
clipRect := cmd.ClipRect()
|
||||
gl.Scissor(int32(clipRect.X), int32(fbHeight)-int32(clipRect.W), int32(clipRect.Z-clipRect.X), int32(clipRect.W-clipRect.Y))
|
||||
|
||||
@ -619,7 +448,9 @@ func drawUI() {
|
||||
}
|
||||
}
|
||||
|
||||
gl.BindVertexArray(imguiInfo.vaoID)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, imguiInfo.vboID)
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, imguiInfo.indexBufID)
|
||||
//Reset gl state
|
||||
gl.Disable(gl.BLEND)
|
||||
gl.Disable(gl.SCISSOR_TEST)
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
}
|
||||
|
||||
114
materials/material.go
Executable file
114
materials/material.go
Executable file
@ -0,0 +1,114 @@
|
||||
package materials
|
||||
|
||||
import (
|
||||
"github.com/bloeys/gglm/gglm"
|
||||
"github.com/bloeys/nmage/buffers"
|
||||
"github.com/bloeys/nmage/logging"
|
||||
"github.com/bloeys/nmage/shaders"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
|
||||
type Material struct {
|
||||
Name string
|
||||
ShaderProg shaders.ShaderProgram
|
||||
}
|
||||
|
||||
func (m *Material) Bind() {
|
||||
gl.UseProgram(m.ShaderProg.ID)
|
||||
}
|
||||
|
||||
func (m *Material) UnBind() {
|
||||
gl.UseProgram(0)
|
||||
}
|
||||
|
||||
func (m *Material) GetAttribLoc(attribName string) int32 {
|
||||
return gl.GetAttribLocation(m.ShaderProg.ID, gl.Str(attribName+"\x00"))
|
||||
}
|
||||
|
||||
func (m *Material) SetAttribute(bufObj buffers.Buffer) {
|
||||
|
||||
bufObj.Bind()
|
||||
|
||||
//NOTE: VBOs are only bound at 'VertexAttribPointer', not BindBUffer, so we need to bind the buffer and vao here
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, bufObj.BufID)
|
||||
|
||||
layout := bufObj.GetLayout()
|
||||
for i := 0; i < len(layout); i++ {
|
||||
gl.EnableVertexAttribArray(uint32(i))
|
||||
gl.VertexAttribPointer(uint32(i), layout[i].ElementType.CompCount(), layout[i].ElementType.GLType(), false, bufObj.Stride, gl.PtrOffset(layout[i].Offset))
|
||||
}
|
||||
|
||||
bufObj.UnBind()
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
}
|
||||
|
||||
func (m *Material) EnableAttribute(attribName string) {
|
||||
gl.EnableVertexAttribArray(uint32(m.GetAttribLoc(attribName)))
|
||||
}
|
||||
|
||||
func (m *Material) DisableAttribute(attribName string) {
|
||||
gl.DisableVertexAttribArray(uint32(m.GetAttribLoc(attribName)))
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifFloat32(uniformName string, val float32) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform1f(m.ShaderProg.ID, loc, val)
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifVec2(uniformName string, vec2 *gglm.Vec2) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform2fv(m.ShaderProg.ID, loc, 1, &vec2.Data[0])
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifVec3(uniformName string, vec3 *gglm.Vec3) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform3fv(m.ShaderProg.ID, loc, 1, &vec3.Data[0])
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifVec4(uniformName string, vec4 *gglm.Vec4) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform4fv(m.ShaderProg.ID, loc, 1, &vec4.Data[0])
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifMat2(uniformName string, mat2 *gglm.Mat2) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix2fv(m.ShaderProg.ID, loc, 1, false, &mat2.Data[0][0])
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifMat3(uniformName string, mat3 *gglm.Mat3) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix3fv(m.ShaderProg.ID, loc, 1, false, &mat3.Data[0][0])
|
||||
}
|
||||
|
||||
func (m *Material) SetUnifMat4(uniformName string, mat4 *gglm.Mat4) {
|
||||
loc := gl.GetUniformLocation(m.ShaderProg.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix4fv(m.ShaderProg.ID, loc, 1, false, &mat4.Data[0][0])
|
||||
}
|
||||
|
||||
func (m *Material) Delete() {
|
||||
gl.DeleteProgram(m.ShaderProg.ID)
|
||||
}
|
||||
|
||||
func NewMaterial(matName, shaderPath string) *Material {
|
||||
|
||||
shdrProg, err := shaders.NewShaderProgram()
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to create new shader program. Err: ", err)
|
||||
}
|
||||
|
||||
vertShader, err := shaders.LoadAndCompilerShader(shaderPath+".vert.glsl", shaders.VertexShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to load and create vertex shader. Err: ", err)
|
||||
}
|
||||
|
||||
fragShader, err := shaders.LoadAndCompilerShader(shaderPath+".frag.glsl", shaders.FragmentShaderType)
|
||||
if err != nil {
|
||||
logging.ErrLog.Fatalln("Failed to load and create fragment shader. Err: ", err)
|
||||
}
|
||||
|
||||
shdrProg.AttachShader(vertShader)
|
||||
shdrProg.AttachShader(fragShader)
|
||||
shdrProg.Link()
|
||||
|
||||
return &Material{Name: matName, ShaderProg: shdrProg}
|
||||
}
|
||||
134
meshes/mesh.go
Executable file
134
meshes/mesh.go
Executable file
@ -0,0 +1,134 @@
|
||||
package meshes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/bloeys/assimp-go/asig"
|
||||
"github.com/bloeys/gglm/gglm"
|
||||
"github.com/bloeys/nmage/asserts"
|
||||
"github.com/bloeys/nmage/buffers"
|
||||
)
|
||||
|
||||
type Mesh struct {
|
||||
Name string
|
||||
Buf buffers.Buffer
|
||||
}
|
||||
|
||||
func NewMesh(name, modelPath string, postProcessFlags asig.PostProcess) (*Mesh, error) {
|
||||
|
||||
scene, release, err := asig.ImportFile(modelPath, asig.PostProcessTriangulate|postProcessFlags)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to load model. Err: " + err.Error())
|
||||
}
|
||||
defer release()
|
||||
|
||||
if len(scene.Meshes) == 0 {
|
||||
return nil, errors.New("No meshes found in file: " + modelPath)
|
||||
}
|
||||
|
||||
mesh := &Mesh{Name: name}
|
||||
sceneMesh := scene.Meshes[0]
|
||||
mesh.Buf = buffers.NewBuffer()
|
||||
|
||||
dataSize := len(sceneMesh.Vertices)*3 + len(sceneMesh.Normals)*3
|
||||
layoutToUse := []buffers.Element{{ElementType: buffers.DataTypeVec3}, {ElementType: buffers.DataTypeVec3}}
|
||||
if len(sceneMesh.ColorSets) > 0 {
|
||||
layoutToUse = append(layoutToUse, buffers.Element{ElementType: buffers.DataTypeVec4})
|
||||
dataSize += len(sceneMesh.ColorSets) * 4
|
||||
}
|
||||
|
||||
mesh.Buf.SetLayout(layoutToUse...)
|
||||
positions := flattenVec3(sceneMesh.Vertices)
|
||||
normals := flattenVec3(sceneMesh.Normals)
|
||||
colors := []float32{}
|
||||
if len(sceneMesh.ColorSets) > 0 {
|
||||
colors = flattenVec4(sceneMesh.ColorSets[0])
|
||||
}
|
||||
|
||||
var values []float32
|
||||
if len(colors) > 0 {
|
||||
values = interleave(
|
||||
arrInfo{values: positions, valsPerComp: 3},
|
||||
arrInfo{values: normals, valsPerComp: 3},
|
||||
arrInfo{values: colors, valsPerComp: 4},
|
||||
)
|
||||
} else {
|
||||
values = interleave(
|
||||
arrInfo{values: positions, valsPerComp: 3},
|
||||
arrInfo{values: normals, valsPerComp: 3},
|
||||
)
|
||||
}
|
||||
|
||||
mesh.Buf.SetData(values)
|
||||
mesh.Buf.SetIndexBufData(flattenFaces(sceneMesh.Faces))
|
||||
return mesh, nil
|
||||
}
|
||||
|
||||
type arrInfo struct {
|
||||
values []float32
|
||||
valsPerComp int
|
||||
}
|
||||
|
||||
func interleave(arrs ...arrInfo) []float32 {
|
||||
|
||||
if len(arrs) == 0 || len(arrs[0].values) == 0 {
|
||||
panic("No input to interleave or arrays are empty")
|
||||
}
|
||||
|
||||
size := 0
|
||||
for i := 0; i < len(arrs); i++ {
|
||||
size += len(arrs[i].values)
|
||||
}
|
||||
|
||||
out := make([]float32, 0, size)
|
||||
for posInArr := 0; posInArr < len(arrs[0].values)/arrs[0].valsPerComp; posInArr++ {
|
||||
for arrToUse := 0; arrToUse < len(arrs); arrToUse++ {
|
||||
for compToAdd := 0; compToAdd < arrs[arrToUse].valsPerComp; compToAdd++ {
|
||||
|
||||
out = append(out, arrs[arrToUse].values[posInArr*arrs[arrToUse].valsPerComp+compToAdd])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func flattenVec3(vec3s []gglm.Vec3) []float32 {
|
||||
|
||||
floats := make([]float32, len(vec3s)*3)
|
||||
for i := 0; i < len(vec3s); i++ {
|
||||
floats[i*3+0] = vec3s[i].X()
|
||||
floats[i*3+1] = vec3s[i].Y()
|
||||
floats[i*3+2] = vec3s[i].Z()
|
||||
}
|
||||
|
||||
return floats
|
||||
}
|
||||
|
||||
func flattenVec4(vec4s []gglm.Vec4) []float32 {
|
||||
|
||||
floats := make([]float32, len(vec4s)*4)
|
||||
for i := 0; i < len(vec4s); i++ {
|
||||
floats[i*4+0] = vec4s[i].X()
|
||||
floats[i*4+1] = vec4s[i].Y()
|
||||
floats[i*4+2] = vec4s[i].Z()
|
||||
floats[i*4+3] = vec4s[i].W()
|
||||
}
|
||||
|
||||
return floats
|
||||
}
|
||||
|
||||
func flattenFaces(faces []asig.Face) []uint32 {
|
||||
|
||||
asserts.T(len(faces[0].Indices) == 3, fmt.Sprintf("Face doesn't have 3 indices. Index count: %v\n", len(faces[0].Indices)))
|
||||
|
||||
uints := make([]uint32, len(faces)*3)
|
||||
for i := 0; i < len(faces); i++ {
|
||||
uints[i*3+0] = uint32(faces[i].Indices[0])
|
||||
uints[i*3+1] = uint32(faces[i].Indices[1])
|
||||
uints[i*3+2] = uint32(faces[i].Indices[2])
|
||||
}
|
||||
|
||||
return uints
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
#version 410
|
||||
|
||||
in vec3 vertPosIn;
|
||||
in vec3 vertColorIn;
|
||||
in vec3 vertNormalIn;
|
||||
layout(location=0) in vec3 vertPosIn;
|
||||
layout(location=1) in vec3 vertNormalIn;
|
||||
layout(location=2) in vec3 vertColorIn;
|
||||
|
||||
out vec3 vertColor;
|
||||
out vec3 vertNormal;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package shaders
|
||||
|
||||
import (
|
||||
"github.com/bloeys/gglm/gglm"
|
||||
"github.com/bloeys/nmage/buffers"
|
||||
"github.com/bloeys/nmage/logging"
|
||||
"github.com/go-gl/gl/v4.1-core/gl"
|
||||
)
|
||||
@ -37,74 +35,3 @@ func (sp *ShaderProgram) Link() {
|
||||
gl.DeleteShader(sp.FragShaderID)
|
||||
}
|
||||
}
|
||||
|
||||
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) 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) SetUnifFloat32(uniformName string, val float32) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform1f(sp.ID, loc, val)
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifVec2(uniformName string, vec2 *gglm.Vec2) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform2fv(sp.ID, loc, 1, &vec2.Data[0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifVec3(uniformName string, vec3 *gglm.Vec3) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform3fv(sp.ID, loc, 1, &vec3.Data[0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifVec4(uniformName string, vec4 *gglm.Vec4) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniform4fv(sp.ID, loc, 1, &vec4.Data[0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifMat2(uniformName string, mat2 *gglm.Mat2) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix2fv(sp.ID, loc, 1, false, &mat2.Data[0][0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifMat3(uniformName string, mat3 *gglm.Mat3) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix3fv(sp.ID, loc, 1, false, &mat3.Data[0][0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) SetUnifMat4(uniformName string, mat4 *gglm.Mat4) {
|
||||
loc := gl.GetUniformLocation(sp.ID, gl.Str(uniformName+"\x00"))
|
||||
gl.ProgramUniformMatrix4fv(sp.ID, loc, 1, false, &mat4.Data[0][0])
|
||||
}
|
||||
|
||||
func (sp *ShaderProgram) Delete() {
|
||||
gl.DeleteProgram(sp.ID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user