raylib-go/examples/shaders/mesh_instancing/main.go
2025-06-22 17:48:18 -04:00

251 lines
7.9 KiB
Go

package main
import (
"fmt"
"math"
rl "git.terah.dev/UnrealXR/raylib-go/raylib"
)
const MAX_INSTANCES = 100000
func main() {
var (
screenWidth = int32(800) // Framebuffer width
screenHeight = int32(450) // Framebuffer height
fps = 60 // Frames per second
speed = 30 // Speed of jump animation
groups = 2 // Count of separate groups jumping around
amp = float32(10) // Maximum amplitude of jump
variance = float32(0.8) // Global variance in jump height
loop = float32(0.0) // Individual cube's computed loop timer
textPositionY int32 = 300
framesCounter = 0
)
rl.SetConfigFlags(rl.FlagMsaa4xHint) // Enable Multi Sampling Anti Aliasing 4x (if available)
rl.InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mesh instancing")
// Define the camera to look into our 3d world
camera := rl.Camera{
Position: rl.NewVector3(-125.0, 125.0, -125.0),
Target: rl.NewVector3(0.0, 0.0, 0.0),
Up: rl.NewVector3(0.0, 1.0, 0.0),
Fovy: 45.0,
Projection: rl.CameraPerspective,
}
cube := rl.GenMeshCube(1.0, 1.0, 1.0)
rotations := make([]rl.Matrix, MAX_INSTANCES) // Rotation state of instances
rotationsInc := make([]rl.Matrix, MAX_INSTANCES) // Per-frame rotation animation of instances
translations := make([]rl.Matrix, MAX_INSTANCES) // Locations of instances
// Scatter random cubes around
for i := 0; i < MAX_INSTANCES; i++ {
x := float32(rl.GetRandomValue(-50, 50))
y := float32(rl.GetRandomValue(-50, 50))
z := float32(rl.GetRandomValue(-50, 50))
translations[i] = rl.MatrixTranslate(x, y, z)
x = float32(rl.GetRandomValue(0, 360))
y = float32(rl.GetRandomValue(0, 360))
z = float32(rl.GetRandomValue(0, 360))
axis := rl.Vector3Normalize(rl.NewVector3(x, y, z))
angle := float32(rl.GetRandomValue(0, 10)) * rl.Deg2rad
rotationsInc[i] = rl.MatrixRotate(axis, angle)
rotations[i] = rl.MatrixIdentity()
}
transforms := make([]rl.Matrix, MAX_INSTANCES)
shader := rl.LoadShader("glsl330/base_lighting_instanced.vs", "glsl330/lighting.fs")
shader.UpdateLocation(rl.ShaderLocMatrixMvp, rl.GetShaderLocation(shader, "mvp"))
shader.UpdateLocation(rl.ShaderLocVectorView, rl.GetShaderLocation(shader, "viewPos"))
shader.UpdateLocation(rl.ShaderLocMatrixModel, rl.GetShaderLocationAttrib(shader, "instanceTransform"))
// ambient light level
ambientLoc := rl.GetShaderLocation(shader, "ambient")
rl.SetShaderValue(shader, ambientLoc, []float32{0.2, 0.2, 0.2, 1.0}, rl.ShaderUniformVec4)
NewLight(LightTypeDirectional, rl.NewVector3(50.0, 50.0, 0.0), rl.Vector3Zero(), rl.White, shader)
material := rl.LoadMaterialDefault()
material.Shader = shader
mmap := material.GetMap(rl.MapDiffuse)
mmap.Color = rl.Red
rl.SetTargetFPS(int32(fps))
for !rl.WindowShouldClose() {
// Update
//----------------------------------------------------------------------------------
textPositionY = 300
framesCounter++
if rl.IsKeyDown(rl.KeyUp) {
amp += 0.5
}
if rl.IsKeyDown(rl.KeyDown) {
if amp <= 1 {
amp = 1
} else {
amp -= 1
}
}
if rl.IsKeyDown(rl.KeyLeft) {
if variance < 0 {
variance = 0
} else {
variance -= 0.01
}
}
if rl.IsKeyDown(rl.KeyRight) {
if variance > 1 {
variance = 1
} else {
variance += 0.01
}
}
if rl.IsKeyDown(rl.KeyOne) {
groups = 1
}
if rl.IsKeyDown(rl.KeyTwo) {
groups = 2
}
if rl.IsKeyDown(rl.KeyThree) {
groups = 3
}
if rl.IsKeyDown(rl.KeyFour) {
groups = 4
}
if rl.IsKeyDown(rl.KeyFive) {
groups = 5
}
if rl.IsKeyDown(rl.KeySix) {
groups = 6
}
if rl.IsKeyDown(rl.KeySeven) {
groups = 7
}
if rl.IsKeyDown(rl.KeyEight) {
groups = 8
}
if rl.IsKeyDown(rl.KeyNine) {
groups = 9
}
if rl.IsKeyDown(rl.KeyW) {
groups = 7
amp = 25
speed = 18
variance = float32(0.70)
}
if rl.IsKeyDown(rl.KeyEqual) {
if float32(speed) <= float32(fps)*0.25 {
speed = int(float32(fps) * 0.25)
} else {
speed = int(float32(speed) * 0.95)
}
}
if rl.IsKeyDown(rl.KeyKpAdd) {
if float32(speed) <= float32(fps)*0.25 {
speed = int(float32(fps) * 0.25)
} else {
speed = int(float32(speed) * 0.95)
}
}
if rl.IsKeyDown(rl.KeyMinus) {
speed = int(math.Max(float64(speed)*1.02, float64(speed)+1))
}
if rl.IsKeyDown(rl.KeyKpSubtract) {
speed = int(math.Max(float64(speed)*1.02, float64(speed)+1))
}
// Update the light shader with the camera view position
rl.SetShaderValue(shader, shader.GetLocation(rl.ShaderLocVectorView),
[]float32{camera.Position.X, camera.Position.Y, camera.Position.Z}, rl.ShaderUniformVec3)
// Apply per-instance transformations
for i := 0; i < MAX_INSTANCES; i++ {
rotations[i] = rl.MatrixMultiply(rotations[i], rotationsInc[i])
transforms[i] = rl.MatrixMultiply(rotations[i], translations[i])
// Get the animation cycle's framesCounter for this instance
loop = float32((framesCounter+int(float32(i%groups)/float32(groups)*float32(speed)))%speed) / float32(speed)
// Calculate the y according to loop cycle
y := float32(math.Sin(float64(loop)*rl.Pi*2)) * amp *
((1 - variance) + (float32(variance) * float32(i%(groups*10)) / float32(groups*10)))
// Clamp to floor
if y < 0 {
y = 0
}
transforms[i] = rl.MatrixMultiply(transforms[i], rl.MatrixTranslate(0.0, y, 0.0))
}
rl.UpdateCamera(&camera, rl.CameraOrbital) // Update camera with orbital camera mode
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl.BeginDrawing()
{
rl.ClearBackground(rl.RayWhite)
rl.BeginMode3D(camera)
//rl.DrawMesh(cube, material, rl.MatrixIdentity())
rl.DrawMeshInstanced(cube, material, transforms, MAX_INSTANCES)
rl.EndMode3D()
rl.DrawText("A CUBE OF DANCING CUBES!", 490, 10, 20, rl.Maroon)
rl.DrawText("PRESS KEYS:", 10, textPositionY, 20, rl.Black)
textPositionY += 25
rl.DrawText("1 - 9", 10, textPositionY, 10, rl.Black)
rl.DrawText(": Number of groups", 50, textPositionY, 10, rl.Black)
rl.DrawText(fmt.Sprintf(": %d", groups), 160, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("UP", 10, textPositionY, 10, rl.Black)
rl.DrawText(": increase amplitude", 50, textPositionY, 10, rl.Black)
rl.DrawText(fmt.Sprintf(": %.2f", amp), 160, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("DOWN", 10, textPositionY, 10, rl.Black)
rl.DrawText(": decrease amplitude", 50, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("LEFT", 10, textPositionY, 10, rl.Black)
rl.DrawText(": decrease variance", 50, textPositionY, 10, rl.Black)
rl.DrawText(fmt.Sprintf(": %.2f", variance), 160, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("RIGHT", 10, textPositionY, 10, rl.Black)
rl.DrawText(": increase variance", 50, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("+/=", 10, textPositionY, 10, rl.Black)
rl.DrawText(": increase speed", 50, textPositionY, 10, rl.Black)
rl.DrawText(fmt.Sprintf(": %d = %f loops/sec", speed, float32(fps)/float32(speed)), 160, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("-", 10, textPositionY, 10, rl.Black)
rl.DrawText(": decrease speed", 50, textPositionY, 10, rl.Black)
textPositionY += 15
rl.DrawText("W", 10, textPositionY, 10, rl.Black)
rl.DrawText(": Wild setup!", 50, textPositionY, 10, rl.Black)
rl.DrawFPS(10, 10)
}
rl.EndDrawing()
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl.CloseWindow() // Close window and OpenGL context
//--------------------------------------------------------------------------------------
}