Merge pull request #285 from unklnik/master

Updated Light.go - reflect.SliceHeader Deprecated
This commit is contained in:
Milan Nikolic 2023-10-10 17:51:30 +02:00 committed by GitHub
commit e9da61431c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 377 additions and 18 deletions

View file

@ -0,0 +1,76 @@
package main
import (
"fmt"
"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
}
func (lt *Light) UpdateValues() {
// Send to shader light enabled state and type
rl.SetShaderValue(lt.shader, lt.enabledLoc, unsafe.Slice((*float32)(unsafe.Pointer(&lt.enabled)), 4), rl.ShaderUniformInt)
rl.SetShaderValue(lt.shader, lt.typeLoc, unsafe.Slice((*float32)(unsafe.Pointer(&lt.lightType)), 4), rl.ShaderUniformInt)
// Send to shader light position values
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)
}

View 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));
}

View file

@ -0,0 +1,32 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
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()
{
// Send vertex attributes to fragment shader
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,103 @@
package main
import (
rl "github.com/gen2brain/raylib-go/raylib"
)
func main() {
screenWidth := int32(1280)
screenHeight := int32(720)
rl.SetConfigFlags(rl.FlagMsaa4xHint) //ENABLE 4X MSAA IF AVAILABLE
rl.InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting")
camera := rl.Camera{}
camera.Position = rl.NewVector3(2.0, 4.0, 6.0)
camera.Target = rl.NewVector3(0.0, 0.5, 0.0)
camera.Up = rl.NewVector3(0.0, 1.0, 0.0)
camera.Fovy = 45.0
camera.Projection = rl.CameraPerspective
ground := rl.LoadModelFromMesh(rl.GenMeshPlane(10, 10, 3, 3))
cube := rl.LoadModelFromMesh(rl.GenMeshCube(2, 4, 2))
shader := rl.LoadShader("lighting.vs", "lighting.fs")
*shader.Locs = rl.GetShaderLocation(shader, "viewPos")
ambientLoc := rl.GetShaderLocation(shader, "ambient")
shaderValue := []float32{0.1, 0.1, 0.1, 1.0}
rl.SetShaderValue(shader, ambientLoc, shaderValue, rl.ShaderUniformVec4)
ground.Materials.Shader = shader
cube.Materials.Shader = shader
lights := make([]Light, 4)
lights[0] = NewLight(LightTypePoint, rl.NewVector3(-2, 1, -2), rl.NewVector3(0, 0, 0), rl.Yellow, shader)
lights[1] = NewLight(LightTypePoint, rl.NewVector3(2, 1, 2), rl.NewVector3(0, 0, 0), rl.Red, shader)
lights[2] = NewLight(LightTypePoint, rl.NewVector3(-2, 1, 2), rl.NewVector3(0, 0, 0), rl.Green, shader)
lights[3] = NewLight(LightTypePoint, rl.NewVector3(2, 1, -2), rl.NewVector3(0, 0, 0), rl.Blue, shader)
rl.SetTargetFPS(60)
for !rl.WindowShouldClose() {
rl.UpdateCamera(&camera, rl.CameraOrbital)
cameraPos := []float32{camera.Position.X, camera.Position.Y, camera.Position.Z}
rl.SetShaderValue(shader, *shader.Locs, cameraPos, rl.ShaderUniformVec3)
if rl.IsKeyPressed(rl.KeyY) {
lights[0].enabled *= -1
}
if rl.IsKeyPressed(rl.KeyR) {
lights[1].enabled *= -1
}
if rl.IsKeyPressed(rl.KeyG) {
lights[2].enabled *= -1
}
if rl.IsKeyPressed(rl.KeyB) {
lights[3].enabled *= -1
}
for i := 0; i < len(lights); i++ {
lights[i].UpdateValues()
}
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.BeginMode3D(camera)
rl.DrawModel(ground, rl.NewVector3(0, 0, 0), 1, rl.White)
rl.DrawModel(cube, rl.NewVector3(0, 0, 0), 1, rl.White)
for i := 0; i < len(lights); i++ {
if lights[i].enabled == 1 {
rl.DrawSphereEx(lights[i].position, 0.2, 8, 8, lights[i].color)
} else {
rl.DrawSphereWires(lights[i].position, 0.2, 8, 8, rl.Fade(lights[i].color, 0.3))
}
}
rl.DrawGrid(10, 1.0) // Draw a grid
rl.EndMode3D()
rl.DrawFPS(10, 10)
rl.DrawText("KEYS [Y] [R] [G] [B] TURN LIGHTS ON/OFF", 10, 40, 20, rl.Black)
rl.EndDrawing()
}
rl.UnloadShader(shader) // Unload shader
rl.UnloadModel(cube) // Unload model
rl.UnloadModel(ground) // Unload model
rl.CloseWindow()
}

View file

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"reflect"
"unsafe" "unsafe"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
@ -22,7 +21,6 @@ type Light struct {
target rl.Vector3 target rl.Vector3
color rl.Color color rl.Color
enabled int32 enabled int32
// shader locations // shader locations
enabledLoc int32 enabledLoc int32
typeLoc int32 typeLoc int32
@ -40,46 +38,32 @@ func NewLight(
position, target rl.Vector3, position, target rl.Vector3,
color rl.Color, color rl.Color,
shader rl.Shader) Light { shader rl.Shader) Light {
light := Light{ light := Light{
shader: shader, shader: shader,
} }
if lightCount < maxLightsCount { if lightCount < maxLightsCount {
light.enabled = 1 light.enabled = 1
light.lightType = lightType light.lightType = lightType
light.position = position light.position = position
light.target = target light.target = target
light.color = color light.color = color
light.enabledLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].enabled", lightCount)) light.enabledLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].enabled", lightCount))
light.typeLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].type", lightCount)) light.typeLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].type", lightCount))
light.posLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].position", lightCount)) light.posLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].position", lightCount))
light.targetLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].target", lightCount)) light.targetLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].target", lightCount))
light.colorLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].color", lightCount)) light.colorLoc = rl.GetShaderLocation(shader, fmt.Sprintf("lights[%d].color", lightCount))
light.UpdateValues() light.UpdateValues()
lightCount++ lightCount++
} }
return light return light
} }
// Send light properties to shader
func (lt *Light) UpdateValues() { func (lt *Light) UpdateValues() {
// not pretty -_-
// need nicer api
sh := &reflect.SliceHeader{
Len: 4,
Cap: 4,
}
// Send to shader light enabled state and type // Send to shader light enabled state and type
sh.Data = uintptr(unsafe.Pointer(&lt.enabled)) rl.SetShaderValue(lt.shader, lt.enabledLoc, unsafe.Slice((*float32)(unsafe.Pointer(&lt.enabled)), 4), rl.ShaderUniformInt)
rl.SetShaderValue(lt.shader, lt.enabledLoc, *(*[]float32)(unsafe.Pointer(sh)), rl.ShaderUniformInt) rl.SetShaderValue(lt.shader, lt.typeLoc, unsafe.Slice((*float32)(unsafe.Pointer(&lt.lightType)), 4), rl.ShaderUniformInt)
// Send to shader light position values // Send to shader light position values
sh.Data = uintptr(unsafe.Pointer(&lt.lightType))
rl.SetShaderValue(lt.shader, lt.posLoc, []float32{lt.position.X, lt.position.Y, lt.position.Z}, rl.ShaderUniformVec3) 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 // Send to shader light target target values

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 KiB

View file

@ -0,0 +1,82 @@
package main
import (
rl "github.com/gen2brain/raylib-go/raylib"
)
var (
numFramesPerLine, numLines = 5, 5
)
func main() {
screenWidth := int32(1280)
screenHeight := int32(720)
rl.InitWindow(screenWidth, screenHeight, "raylib [shapes] example - sprite explosion")
rl.InitAudioDevice()
fxBoom := rl.LoadSound("boom.wav")
explosion := rl.LoadTexture("explosion.png")
frameW := float32(explosion.Width / int32(numFramesPerLine))
frameH := float32(explosion.Height / int32(numLines))
currentFrame, currentLine := 0, 0
frameRec := rl.NewRectangle(0, 0, frameW, frameH)
position := rl.NewVector2(0, 0)
active := false
framesCount := 0
rl.SetTargetFPS(120)
for !rl.WindowShouldClose() {
if rl.IsMouseButtonPressed(rl.MouseLeftButton) && !active {
position = rl.GetMousePosition()
active = true
position.X -= frameW / 2
position.Y -= frameH / 2
rl.PlaySound(fxBoom)
}
if active {
framesCount++
if framesCount > 2 {
currentFrame++
if currentFrame >= numFramesPerLine {
currentFrame = 0
currentLine++
if currentLine >= numLines {
currentLine = 0
active = false
}
}
framesCount = 0
}
}
frameRec.X = frameW * float32(currentFrame)
frameRec.Y = frameH * float32(currentLine)
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.DrawText("click left mouse on screen to explode", 19, 21, 20, rl.Red)
rl.DrawText("click left mouse on screen to explode", 20, 20, 20, rl.Black)
if active {
rl.DrawTextureRec(explosion, frameRec, position, rl.White)
}
rl.EndDrawing()
}
rl.UnloadTexture(explosion)
rl.UnloadSound(fxBoom)
rl.CloseAudioDevice()
rl.CloseWindow()
}