Merge pull request #9 from mmcilroy/example_shaders_basic_lighting
Basic lighting example
This commit is contained in:
commit
f976ee2333
76
examples/shaders/lighting.fs
Normal file
76
examples/shaders/lighting.fs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#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 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/lighting.vs
Normal file
32
examples/shaders/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);
|
||||||
|
}
|
188
examples/shaders_basic_lighting.rs
Normal file
188
examples/shaders_basic_lighting.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
use raylib_ffi::*;
|
||||||
|
use ::std::os::raw::*;
|
||||||
|
|
||||||
|
const MAX_LIGHTS: usize = 4; // Max dynamic lights supported by shader
|
||||||
|
|
||||||
|
// Light data
|
||||||
|
struct Light {
|
||||||
|
enabled: i32,
|
||||||
|
kind: i32,
|
||||||
|
position: Vector3,
|
||||||
|
target: Vector3,
|
||||||
|
color: Color,
|
||||||
|
|
||||||
|
// Shader locations
|
||||||
|
enabled_loc: i32,
|
||||||
|
kind_loc: i32,
|
||||||
|
position_loc: i32,
|
||||||
|
target_loc: i32,
|
||||||
|
color_loc: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a light and get shader locations
|
||||||
|
fn create_light(id: isize, kind: i32, position: Vector3, target : Vector3, color : Color, shader : Shader) -> Light {
|
||||||
|
unsafe {
|
||||||
|
let light = Light {
|
||||||
|
enabled: 1,
|
||||||
|
kind,
|
||||||
|
position,
|
||||||
|
target,
|
||||||
|
color,
|
||||||
|
|
||||||
|
// NOTE: Lighting shader naming must be the provided ones
|
||||||
|
enabled_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].enabled", id))),
|
||||||
|
kind_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].type", id))),
|
||||||
|
position_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].position", id))),
|
||||||
|
target_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].target", id))),
|
||||||
|
color_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].color", id)))
|
||||||
|
};
|
||||||
|
|
||||||
|
update_light_values(shader, &light);
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send light properties to shader
|
||||||
|
// NOTE: Light shader locations should be available
|
||||||
|
fn update_light_values(shader: Shader, light: &Light) {
|
||||||
|
unsafe {
|
||||||
|
// Send to shader light enabled state and type
|
||||||
|
let enabled = [light.enabled].as_ptr();
|
||||||
|
SetShaderValue(shader, light.enabled_loc, enabled as *const c_void, enums::ShaderUniformDataType::Int as i32);
|
||||||
|
let kind = [light.kind].as_ptr();
|
||||||
|
SetShaderValue(shader, light.kind_loc, kind as *const c_void, enums::ShaderUniformDataType::Int as i32);
|
||||||
|
|
||||||
|
// Send to shader light position values
|
||||||
|
let position = [light.position.x, light.position.y, light.position.z].as_ptr();
|
||||||
|
SetShaderValue(shader, light.position_loc, position as *const c_void, enums::ShaderUniformDataType::Vec3 as i32);
|
||||||
|
|
||||||
|
// Send to shader light target position values
|
||||||
|
let target = [light.position.x, light.position.y, light.position.z].as_ptr();
|
||||||
|
SetShaderValue(shader, light.target_loc, target as *const c_void, enums::ShaderUniformDataType::Vec3 as i32);
|
||||||
|
|
||||||
|
// Send to shader light color values
|
||||||
|
let color = [
|
||||||
|
light.color.r as f32 / 255.0,
|
||||||
|
light.color.g as f32 / 255.0,
|
||||||
|
light.color.b as f32 / 255.0,
|
||||||
|
light.color.a as f32 / 255.0
|
||||||
|
].as_ptr();
|
||||||
|
SetShaderValue(shader, light.color_loc, color as *const c_void, enums::ShaderUniformDataType::Vec4 as i32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
pub fn main() {
|
||||||
|
unsafe {
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
SetConfigFlags(enums::ConfigFlags::Msaa4xHint as u32); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||||
|
InitWindow(800, 450, rl_str!("raylib [shaders] example - basic lighting"));
|
||||||
|
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
let mut camera = Camera{
|
||||||
|
position: Vector3{ x: 2.0, y: 4.0, z: 6.0 }, // Camera position
|
||||||
|
target: Vector3{ x: 0.0, y: 0.5, z: 0.0 }, // Camera looking at point
|
||||||
|
up: Vector3{ x: 0.0, y: 1.0, z: 0.0 }, // Camera up vector (rotation towards target)
|
||||||
|
fovy: 45.0, // Camera field-of-view Y
|
||||||
|
projection: enums::CameraProjection::Perspective as i32 // Camera projection type
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load plane model from a generated mesh
|
||||||
|
let model = LoadModelFromMesh(GenMeshPlane(10.0, 10.0, 3, 3));
|
||||||
|
let cube = LoadModelFromMesh(GenMeshCube(2.0, 4.0, 2.0));
|
||||||
|
|
||||||
|
// Load basic lighting shader
|
||||||
|
let shader = LoadShader(rl_str!("examples/shaders/lighting.vs"), rl_str!("examples/shaders/lighting.fs"));
|
||||||
|
|
||||||
|
// Get some required shader locations
|
||||||
|
let view_loc = shader.locs.offset(enums::ShaderLocationIndex::VectorView as isize) as *mut c_int;
|
||||||
|
*view_loc = GetShaderLocation(shader, rl_str!("viewPos"));
|
||||||
|
|
||||||
|
// Ambient light level (some basic lighting)
|
||||||
|
let ambient_loc = GetShaderLocation(shader, rl_str!("ambient"));
|
||||||
|
let ambient_value = [0.1 as f32, 0.1 as f32, 0.1 as f32, 1.0 as f32].as_ptr();
|
||||||
|
SetShaderValue(shader, ambient_loc, ambient_value as *const c_void, enums::ShaderUniformDataType::Ivec4 as i32);
|
||||||
|
|
||||||
|
// Assign lighting shader to model
|
||||||
|
(*(model.materials.offset(0))).shader = shader;
|
||||||
|
(*(cube.materials.offset(0))).shader = shader;
|
||||||
|
|
||||||
|
// Create lights
|
||||||
|
let mut lights = [
|
||||||
|
create_light(0, 1, Vector3{ x: -2.0, y: 1.0, z: -2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::YELLOW, shader),
|
||||||
|
create_light(1, 1, Vector3{ x: 2.0, y: 1.0, z: 2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::RED, shader),
|
||||||
|
create_light(2, 1, Vector3{ x: -2.0, y: 1.0, z: 2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::GREEN, shader),
|
||||||
|
create_light(3, 1, Vector3{ x: 2.0, y: 1.0, z: -2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::BLUE, shader)
|
||||||
|
];
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while !WindowShouldClose() // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
UpdateCamera(&mut camera, enums::CameraMode::Orbital as i32);
|
||||||
|
|
||||||
|
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||||
|
let camera_pos = [camera.position.x, camera.position.y, camera.position.z].as_ptr();
|
||||||
|
SetShaderValue(shader, shader.locs.offset(enums::ShaderLocationIndex::VectorView as isize).read(), camera_pos as *mut c_void, enums::ShaderUniformDataType::Ivec3 as c_int);
|
||||||
|
|
||||||
|
// Check key inputs to enable/disable lights
|
||||||
|
if IsKeyPressed(enums::KeyboardKey::R as i32) { lights[1].enabled = !lights[1].enabled; }
|
||||||
|
if IsKeyPressed(enums::KeyboardKey::G as i32) { lights[2].enabled = !lights[2].enabled; }
|
||||||
|
if IsKeyPressed(enums::KeyboardKey::B as i32) { lights[3].enabled = !lights[3].enabled; }
|
||||||
|
if IsKeyPressed(enums::KeyboardKey::Y as i32) { lights[0].enabled = !lights[0].enabled; }
|
||||||
|
|
||||||
|
// Update light values (actually, only enable/disable them)
|
||||||
|
for i in 0 .. MAX_LIGHTS {
|
||||||
|
update_light_values(shader, &lights[i]);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(colors::WHITE);
|
||||||
|
|
||||||
|
BeginMode3D(camera);
|
||||||
|
|
||||||
|
DrawModel(model, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, 1.0, colors::WHITE);
|
||||||
|
DrawModel(cube, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, 1.0, colors::WHITE);
|
||||||
|
|
||||||
|
// Draw spheres to show where the lights are
|
||||||
|
for i in 0 .. MAX_LIGHTS {
|
||||||
|
if lights[i].enabled > 0 {
|
||||||
|
DrawSphereEx(lights[i].position, 0.2, 8, 8, lights[i].color);
|
||||||
|
} else {
|
||||||
|
DrawSphereWires(lights[i].position, 0.2, 8, 8, ColorAlpha(lights[i].color, 0.3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawGrid(10, 1.0);
|
||||||
|
|
||||||
|
EndMode3D();
|
||||||
|
|
||||||
|
DrawFPS(10, 10);
|
||||||
|
|
||||||
|
DrawText(rl_str!("Use keys [Y][R][G][B] to toggle lights"), 10, 40, 20, colors::DARKGRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadModel(model); // Unload the model
|
||||||
|
UnloadModel(cube); // Unload the model
|
||||||
|
UnloadShader(shader); // Unload shader
|
||||||
|
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user