Add api and example for mesh drawing.
This commit is contained in:
parent
ace572fead
commit
15ed58856b
7 changed files with 510 additions and 18 deletions
|
@ -0,0 +1,36 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
in vec3 vertexPosition;
|
||||||
|
in vec2 vertexTexCoord;
|
||||||
|
in vec3 vertexNormal;
|
||||||
|
in vec4 vertexColor;
|
||||||
|
|
||||||
|
in mat4 instanceTransform;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 matNormal;
|
||||||
|
|
||||||
|
// Output vertex attributes (to fragment shader)
|
||||||
|
out vec3 fragPosition;
|
||||||
|
out vec2 fragTexCoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
out vec3 fragNormal;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Compute MVP for current instance
|
||||||
|
mat4 mvpi = mvp*instanceTransform;
|
||||||
|
|
||||||
|
// Send vertex attributes to fragment shader
|
||||||
|
fragPosition = vec3(mvpi*vec4(vertexPosition, 1.0));
|
||||||
|
fragTexCoord = vertexTexCoord;
|
||||||
|
fragColor = vertexColor;
|
||||||
|
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
|
||||||
|
|
||||||
|
// Calculate final vertex position
|
||||||
|
gl_Position = mvpi*vec4(vertexPosition, 1.0);
|
||||||
|
}
|
82
examples/shaders/mesh_instancing/glsl330/lighting.fs
Normal file
82
examples/shaders/mesh_instancing/glsl330/lighting.fs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input vertex attributes (from vertex shader)
|
||||||
|
in vec3 fragPosition;
|
||||||
|
in vec2 fragTexCoord;
|
||||||
|
in vec4 fragColor;
|
||||||
|
in vec3 fragNormal;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
|
// Output fragment color
|
||||||
|
out vec4 finalColor;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
#define MAX_LIGHTS 4
|
||||||
|
#define LIGHT_DIRECTIONAL 0
|
||||||
|
#define LIGHT_POINT 1
|
||||||
|
|
||||||
|
struct MaterialProperty {
|
||||||
|
vec3 color;
|
||||||
|
int useSampler;
|
||||||
|
sampler2D sampler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
int enabled;
|
||||||
|
int type;
|
||||||
|
vec3 position;
|
||||||
|
vec3 target;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Input lighting values
|
||||||
|
uniform Light lights[MAX_LIGHTS];
|
||||||
|
uniform vec4 ambient;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Texel color fetching from texture sampler
|
||||||
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
vec3 lightDot = vec3(0.0);
|
||||||
|
vec3 normal = normalize(fragNormal);
|
||||||
|
vec3 viewD = normalize(viewPos - fragPosition);
|
||||||
|
vec3 specular = vec3(0.0);
|
||||||
|
|
||||||
|
// NOTE: Implement here your fragment shader code
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
{
|
||||||
|
if (lights[i].enabled == 1)
|
||||||
|
{
|
||||||
|
vec3 light = vec3(0.0);
|
||||||
|
|
||||||
|
if (lights[i].type == LIGHT_DIRECTIONAL)
|
||||||
|
{
|
||||||
|
light = -normalize(lights[i].target - lights[i].position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lights[i].type == LIGHT_POINT)
|
||||||
|
{
|
||||||
|
light = normalize(lights[i].position - fragPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
float NdotL = max(dot(normal, light), 0.0);
|
||||||
|
lightDot += lights[i].color.rgb*NdotL;
|
||||||
|
|
||||||
|
float specCo = 0.0;
|
||||||
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine
|
||||||
|
specular += specCo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0)));
|
||||||
|
finalColor += texelColor*(ambient/10.0)*colDiffuse;
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
finalColor = pow(finalColor, vec4(1.0/2.2));
|
||||||
|
}
|
92
examples/shaders/mesh_instancing/light.go
Normal file
92
examples/shaders/mesh_instancing/light.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LightType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
LightTypeDirectional LightType = iota
|
||||||
|
LightTypePoint
|
||||||
|
)
|
||||||
|
|
||||||
|
type Light struct {
|
||||||
|
shader rl.Shader
|
||||||
|
lightType LightType
|
||||||
|
position rl.Vector3
|
||||||
|
target rl.Vector3
|
||||||
|
color rl.Color
|
||||||
|
enabled int32
|
||||||
|
|
||||||
|
// shader locations
|
||||||
|
enabledLoc int32
|
||||||
|
typeLoc int32
|
||||||
|
posLoc int32
|
||||||
|
targetLoc int32
|
||||||
|
colorLoc int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxLightsCount = 4
|
||||||
|
|
||||||
|
var lightCount = 0
|
||||||
|
|
||||||
|
func NewLight(
|
||||||
|
lightType LightType,
|
||||||
|
position, target rl.Vector3,
|
||||||
|
color rl.Color,
|
||||||
|
shader rl.Shader) Light {
|
||||||
|
|
||||||
|
light := Light{
|
||||||
|
shader: shader,
|
||||||
|
}
|
||||||
|
|
||||||
|
if lightCount < maxLightsCount {
|
||||||
|
light.enabled = 1
|
||||||
|
light.lightType = lightType
|
||||||
|
light.position = position
|
||||||
|
light.target = target
|
||||||
|
light.color = color
|
||||||
|
|
||||||
|
light.enabledLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].enabled", lightCount))
|
||||||
|
light.typeLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].type", lightCount))
|
||||||
|
light.posLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].position", lightCount))
|
||||||
|
light.targetLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].target", lightCount))
|
||||||
|
light.colorLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].color", lightCount))
|
||||||
|
light.UpdateValues()
|
||||||
|
|
||||||
|
lightCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
return light
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send light properties to shader
|
||||||
|
func (lt *Light) UpdateValues() {
|
||||||
|
// not pretty -_-
|
||||||
|
// need nicer api
|
||||||
|
sh := &reflect.SliceHeader{
|
||||||
|
Len: 4,
|
||||||
|
Cap: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to shader light enabled state and type
|
||||||
|
sh.Data = uintptr(unsafe.Pointer(<.enabled))
|
||||||
|
rl.SetShaderValue(lt.shader, lt.enabledLoc, *(*[]float32)(unsafe.Pointer(sh)), rl.ShaderUniformInt)
|
||||||
|
|
||||||
|
// Send to shader light position values
|
||||||
|
sh.Data = uintptr(unsafe.Pointer(<.lightType))
|
||||||
|
rl.SetShaderValue(lt.shader, lt.posLoc, []float32{lt.position.X, lt.position.Y, lt.position.Z}, rl.ShaderUniformVec3)
|
||||||
|
|
||||||
|
// Send to shader light target target values
|
||||||
|
rl.SetShaderValue(lt.shader, lt.targetLoc, []float32{lt.target.X, lt.target.Y, lt.target.Z}, rl.ShaderUniformVec3)
|
||||||
|
|
||||||
|
// Send to shader light color values
|
||||||
|
rl.SetShaderValue(lt.shader, lt.colorLoc,
|
||||||
|
[]float32{float32(lt.color.R) / 255, float32(lt.color.G) / 255, float32(lt.color.B) / 255, float32(lt.color.A) / 255},
|
||||||
|
rl.ShaderUniformVec4)
|
||||||
|
}
|
253
examples/shaders/mesh_instancing/main.go
Normal file
253
examples/shaders/mesh_instancing/main.go
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/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.LocMatrixMvp, rl.GetShaderLocation(shader, "mvp"))
|
||||||
|
shader.UpdateLocation(rl.LocVectorView, rl.GetShaderLocation(shader, "viewPos"))
|
||||||
|
shader.UpdateLocation(rl.LocMatrixModel, 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.SetCameraMode(camera, rl.CameraOrbital)
|
||||||
|
|
||||||
|
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.LocVectorView),
|
||||||
|
[]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) // Update camera
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
}
|
|
@ -400,6 +400,16 @@ func DrawBillboardRec(camera Camera, texture Texture2D, sourceRec Rectangle, cen
|
||||||
C.DrawBillboardRec(*ccamera, *ctexture, *csourceRec, *ccenter, *csize, *ctint)
|
C.DrawBillboardRec(*ccamera, *ctexture, *csourceRec, *ccenter, *csize, *ctint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawMesh - Draw a single mesh
|
||||||
|
func DrawMesh(mesh Mesh, material Material, transform Matrix) {
|
||||||
|
C.DrawMesh(*mesh.cptr(), *material.cptr(), *transform.cptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawMeshInstanced - Draw mesh with instanced rendering
|
||||||
|
func DrawMeshInstanced(mesh Mesh, material Material, transforms []Matrix, instances int) {
|
||||||
|
C.DrawMeshInstanced(*mesh.cptr(), *material.cptr(), transforms[0].cptr(), C.int(instances))
|
||||||
|
}
|
||||||
|
|
||||||
// GetMeshBoundingBox - Compute mesh bounding box limits
|
// GetMeshBoundingBox - Compute mesh bounding box limits
|
||||||
func GetMeshBoundingBox(mesh Mesh) BoundingBox {
|
func GetMeshBoundingBox(mesh Mesh) BoundingBox {
|
||||||
cmesh := mesh.cptr()
|
cmesh := mesh.cptr()
|
||||||
|
|
|
@ -716,8 +716,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Shader location point type
|
// Shader location point type
|
||||||
|
type LocationPointType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LocVertexPosition = iota
|
LocVertexPosition LocationPointType = iota
|
||||||
LocVertexTexcoord01
|
LocVertexTexcoord01
|
||||||
LocVertexTexcoord02
|
LocVertexTexcoord02
|
||||||
LocVertexNormal
|
LocVertexNormal
|
||||||
|
@ -746,8 +748,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Material map type
|
// Material map type
|
||||||
|
type MaterialMapType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MapAlbedo = iota
|
MapAlbedo MaterialMapType = iota
|
||||||
MapMetalness
|
MapMetalness
|
||||||
MapNormal
|
MapNormal
|
||||||
MapRoughness
|
MapRoughness
|
||||||
|
@ -830,6 +834,11 @@ func newMaterialFromPointer(ptr unsafe.Pointer) Material {
|
||||||
return *(*Material)(ptr)
|
return *(*Material)(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMap - Get pointer to MaterialMap by map type
|
||||||
|
func (mt Material) GetMap(index MaterialMapType) *MaterialMap {
|
||||||
|
return (*MaterialMap)(unsafe.Pointer(uintptr(unsafe.Pointer(mt.Maps)) + uintptr(index)*uintptr(unsafe.Sizeof(MaterialMap{}))))
|
||||||
|
}
|
||||||
|
|
||||||
// MaterialMap type
|
// MaterialMap type
|
||||||
type MaterialMap struct {
|
type MaterialMap struct {
|
||||||
// Texture
|
// Texture
|
||||||
|
@ -920,6 +929,16 @@ func newShaderFromPointer(ptr unsafe.Pointer) Shader {
|
||||||
return *(*Shader)(ptr)
|
return *(*Shader)(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLocation - Get shader value's location
|
||||||
|
func (sh Shader) GetLocation(index LocationPointType) int32 {
|
||||||
|
return *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(sh.Locs)) + uintptr(index*4)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLocation - Update shader value's location
|
||||||
|
func (sh Shader) UpdateLocation(index LocationPointType, loc int32) {
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(sh.Locs)) + uintptr(index*4))) = loc
|
||||||
|
}
|
||||||
|
|
||||||
// CharInfo - Font character info
|
// CharInfo - Font character info
|
||||||
type CharInfo struct {
|
type CharInfo struct {
|
||||||
// Character value (Unicode)
|
// Character value (Unicode)
|
||||||
|
|
|
@ -673,22 +673,22 @@ func MatrixScale(x, y, z float32) Matrix {
|
||||||
func MatrixMultiply(left, right Matrix) Matrix {
|
func MatrixMultiply(left, right Matrix) Matrix {
|
||||||
var result Matrix
|
var result Matrix
|
||||||
|
|
||||||
result.M0 = right.M0*left.M0 + right.M1*left.M4 + right.M2*left.M8 + right.M3*left.M12
|
result.M0 = left.M0*right.M0 + left.M1*right.M4 + left.M2*right.M8 + left.M3*right.M12
|
||||||
result.M1 = right.M0*left.M1 + right.M1*left.M5 + right.M2*left.M9 + right.M3*left.M13
|
result.M1 = left.M0*right.M1 + left.M1*right.M5 + left.M2*right.M9 + left.M3*right.M13
|
||||||
result.M2 = right.M0*left.M2 + right.M1*left.M6 + right.M2*left.M10 + right.M3*left.M14
|
result.M2 = left.M0*right.M2 + left.M1*right.M6 + left.M2*right.M10 + left.M3*right.M14
|
||||||
result.M3 = right.M0*left.M3 + right.M1*left.M7 + right.M2*left.M11 + right.M3*left.M15
|
result.M3 = left.M0*right.M3 + left.M1*right.M7 + left.M2*right.M11 + left.M3*right.M15
|
||||||
result.M4 = right.M4*left.M0 + right.M5*left.M4 + right.M6*left.M8 + right.M7*left.M12
|
result.M4 = left.M4*right.M0 + left.M5*right.M4 + left.M6*right.M8 + left.M7*right.M12
|
||||||
result.M5 = right.M4*left.M1 + right.M5*left.M5 + right.M6*left.M9 + right.M7*left.M13
|
result.M5 = left.M4*right.M1 + left.M5*right.M5 + left.M6*right.M9 + left.M7*right.M13
|
||||||
result.M6 = right.M4*left.M2 + right.M5*left.M6 + right.M6*left.M10 + right.M7*left.M14
|
result.M6 = left.M4*right.M2 + left.M5*right.M6 + left.M6*right.M10 + left.M7*right.M14
|
||||||
result.M7 = right.M4*left.M3 + right.M5*left.M7 + right.M6*left.M11 + right.M7*left.M15
|
result.M7 = left.M4*right.M3 + left.M5*right.M7 + left.M6*right.M11 + left.M7*right.M15
|
||||||
result.M8 = right.M8*left.M0 + right.M9*left.M4 + right.M10*left.M8 + right.M11*left.M12
|
result.M8 = left.M8*right.M0 + left.M9*right.M4 + left.M10*right.M8 + left.M11*right.M12
|
||||||
result.M9 = right.M8*left.M1 + right.M9*left.M5 + right.M10*left.M9 + right.M11*left.M13
|
result.M9 = left.M8*right.M1 + left.M9*right.M5 + left.M10*right.M9 + left.M11*right.M13
|
||||||
result.M10 = right.M8*left.M2 + right.M9*left.M6 + right.M10*left.M10 + right.M11*left.M14
|
result.M10 = left.M8*right.M2 + left.M9*right.M6 + left.M10*right.M10 + left.M11*right.M14
|
||||||
result.M11 = right.M8*left.M3 + right.M9*left.M7 + right.M10*left.M11 + right.M11*left.M15
|
result.M11 = left.M8*right.M3 + left.M9*right.M7 + left.M10*right.M11 + left.M11*right.M15
|
||||||
result.M12 = right.M12*left.M0 + right.M13*left.M4 + right.M14*left.M8 + right.M15*left.M12
|
result.M12 = left.M12*right.M0 + left.M13*right.M4 + left.M14*right.M8 + left.M15*right.M12
|
||||||
result.M13 = right.M12*left.M1 + right.M13*left.M5 + right.M14*left.M9 + right.M15*left.M13
|
result.M13 = left.M12*right.M1 + left.M13*right.M5 + left.M14*right.M9 + left.M15*right.M13
|
||||||
result.M14 = right.M12*left.M2 + right.M13*left.M6 + right.M14*left.M10 + right.M15*left.M14
|
result.M14 = left.M12*right.M2 + left.M13*right.M6 + left.M14*right.M10 + left.M15*right.M14
|
||||||
result.M15 = right.M12*left.M3 + right.M13*left.M7 + right.M14*left.M11 + right.M15*left.M15
|
result.M15 = left.M12*right.M3 + left.M13*right.M7 + left.M14*right.M11 + left.M15*right.M15
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue