raylib/ports/shaders

Licence This example has its own licence, rather than Odin's: raylib/ports/LICENSE
These are ported Raylib examples, and as such, they are subject to Raylib's license. Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
The rest of the licence
This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

Code

shaders_mesh_instancing.odin ¶
85 linesSource

1package main
2
3import    "rlights"
4
5import rl "vendor:raylib"
6
7MAX_INSTANCES :: 10_000
8
9main :: proc() {
10	screenWidth  :: 800
11	screenHeight :: 450
12
13	rl.InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mesh instancing")
14	defer rl.CloseWindow()
15
16	camera := rl.Camera{
17        position   = { -125, 125, -125 },
18        target     = 0,
19        up         = { 0, 1, 0 },
20        fovy       = 45,
21        projection = .PERSPECTIVE,
22    }
23
24	cube := rl.GenMeshCube(1, 1, 1)
25
26	transforms := make([]rl.Matrix, MAX_INSTANCES)
27	defer delete(transforms)
28
29	for i in 0..<MAX_INSTANCES {
30		translation := rl.MatrixTranslate(f32(rl.GetRandomValue(-50, 50)), f32(rl.GetRandomValue(-50, 50)), f32(rl.GetRandomValue(-50, 50)))
31		axis        := rl.Vector3Normalize({f32(rl.GetRandomValue(0, 360)), f32(rl.GetRandomValue(0, 360)), f32(rl.GetRandomValue(0, 360))})
32		angle       := f32(rl.GetRandomValue(0, 10)) * f32(rl.DEG2RAD)
33		rotation    := rl.MatrixRotate(axis, angle)
34
35		transforms[i] = rotation * translation
36	}
37
38	shader := rl.LoadShader("resources/shaders/lighting_instancing.vs", "resources/shaders/lighting.fs")
39	defer rl.UnloadShader(shader)
40
41	shader.locs[rl.ShaderLocationIndex.MATRIX_MVP]   = i32(rl.GetShaderLocation(shader, "mvp"))
42	shader.locs[rl.ShaderLocationIndex.VECTOR_VIEW]  = i32(rl.GetShaderLocation(shader, "viewPos"))
43	shader.locs[rl.ShaderLocationIndex.MATRIX_MODEL] = i32(rl.GetShaderLocationAttrib(shader, "instanceTransform"))
44
45	ambientLoc := rl.GetShaderLocation(shader, "ambient")
46	rl.SetShaderValue(shader, ambientLoc, &[4]f32{ 0.2, 0.2, 0.2, 1 }, .VEC4)
47
48	rlights.CreateLight(.Directional, { 50, 50, 0 }, 0, rl.WHITE, shader)
49
50	matInstances := rl.LoadMaterialDefault()
51	matInstances.shader = shader
52	matInstances.maps[rl.MaterialMapIndex.ALBEDO].color = rl.RED
53
54	matDefault := rl.LoadMaterialDefault()
55	matDefault.maps[rl.MaterialMapIndex.ALBEDO].color = rl.BLUE
56
57	rl.SetTargetFPS(60)
58
59	for !rl.WindowShouldClose() {
60		rl.UpdateCamera(&camera, .ORBITAL)
61
62		cameraPos := [3]f32{ camera.position.x, camera.position.y, camera.position.z }
63		rl.SetShaderValue(shader, rl.ShaderLocationIndex(shader.locs[rl.ShaderLocationIndex.VECTOR_VIEW]), &cameraPos, .VEC3)
64
65		{
66			rl.BeginDrawing()
67			defer rl.EndDrawing()
68
69			rl.ClearBackground(rl.RAYWHITE)
70			
71			{
72				rl.BeginMode3D(camera)
73				defer rl.EndMode3D()
74
75				rl.DrawMesh(cube, matDefault, rl.MatrixTranslate(-10, 0, 0))
76
77				rl.DrawMeshInstanced(cube, matInstances, raw_data(transforms), MAX_INSTANCES)
78
79				rl.DrawMesh(cube, matDefault, rl.MatrixTranslate(10, 0, 0))
80			}
81
82			rl.DrawFPS(10, 10)
83		}
84	}
85}

Shaders

resources/shaders/lighting.fs ¶
76 linesSource

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

resources/shaders/lighting_instancing.vs ¶
36 linesSource

#version 330

// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
//in vec4 vertexColor;      // Not required

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

Declarations Used 33