updated light.go added basic lighting example
This commit is contained in:
parent
d97aa6e3f6
commit
d3497d36da
5 changed files with 295 additions and 18 deletions
76
examples/shaders/basic_lighting/light.go
Normal file
76
examples/shaders/basic_lighting/light.go
Normal 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(<.enabled)), 4), rl.ShaderUniformInt)
|
||||||
|
rl.SetShaderValue(lt.shader, lt.typeLoc, unsafe.Slice((*float32)(unsafe.Pointer(<.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)
|
||||||
|
}
|
82
examples/shaders/basic_lighting/lighting.fs
Normal file
82
examples/shaders/basic_lighting/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));
|
||||||
|
}
|
32
examples/shaders/basic_lighting/lighting.vs
Normal file
32
examples/shaders/basic_lighting/lighting.vs
Normal 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);
|
||||||
|
}
|
103
examples/shaders/basic_lighting/main.go
Normal file
103
examples/shaders/basic_lighting/main.go
Normal 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()
|
||||||
|
}
|
|
@ -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(<.enabled))
|
rl.SetShaderValue(lt.shader, lt.enabledLoc, unsafe.Slice((*float32)(unsafe.Pointer(<.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(<.lightType)), 4), rl.ShaderUniformInt)
|
||||||
|
|
||||||
// Send to shader light position values
|
// 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)
|
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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue