Draw Mesh Instanced Example.

This commit is contained in:
jussi
2022-12-09 16:02:28 +02:00
parent 973d902a16
commit e1a85f898e
11 changed files with 282 additions and 16 deletions

12
API.md
View File

@@ -4070,7 +4070,6 @@ Draw a 3d mesh with material and transform
> success = RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances ) > success = RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances )
Draw multiple mesh instances with material and different transforms Draw multiple mesh instances with material and different transforms
Note! Untested.
- Failure return false - Failure return false
- Success return true - Success return true
@@ -4171,6 +4170,15 @@ Set value for a material map type
--- ---
> success = RL_SetMaterialShader( Material material, Shader shader )
Set shader for material
- Failure return false
- Success return true
---
## Models - Model ## Models - Model
--- ---
@@ -5363,7 +5371,7 @@ Invert provided matrix
--- ---
> result = MatrixIdentity() > result = RL_MatrixIdentity()
Get identity matrix Get identity matrix

View File

@@ -10,6 +10,7 @@ KEY CHANGES:
- ADDED: Flag option (-s) for doc_parser.lua for exporting module APIs to separate files. - ADDED: Flag option (-s) for doc_parser.lua for exporting module APIs to separate files.
- ADDED: ReiLuaGui. - ADDED: ReiLuaGui.
- ADDED: ReiLuaGui Examples. - ADDED: ReiLuaGui Examples.
- ADDED: Draw Mesh Instanced Example.
Detailed changes: Detailed changes:
ADDED: Help argument. ADDED: Help argument.
@@ -21,3 +22,4 @@ FIXED: RL_DrawLineBezierQuad was called RL_DrawLineBezier in API.
ADDED: Color lib. ADDED: Color lib.
FIXED: RL_DrawEllipse and RL_DrawEllipseLines expecting wrong arguments. FIXED: RL_DrawEllipse and RL_DrawEllipseLines expecting wrong arguments.
ADDED: RL_IsPathFile. ADDED: RL_IsPathFile.
ADDED: RL_SetMaterialShader.

View File

@@ -1,3 +1,6 @@
-- Forked from raylib-lua example by TSnake41
-- https://github.com/TSnake41/raylib-lua/blob/master/examples/textures_bunnymark.lua
local MAX_BUNNIES = 100000 local MAX_BUNNIES = 100000
-- This is the maximum amount of elements (quads) per batch -- This is the maximum amount of elements (quads) per batch
@@ -39,8 +42,6 @@ function Bunny:update()
end end
end end
-- Init
function init() function init()
RL_SetWindowState( FLAG_VSYNC_HINT ) RL_SetWindowState( FLAG_VSYNC_HINT )
RL_SetWindowSize( { screenWidth, screenHeight } ) RL_SetWindowSize( { screenWidth, screenHeight } )
@@ -50,8 +51,6 @@ function init()
texSize = RL_GetTextureSize( texBunny ) texSize = RL_GetTextureSize( texBunny )
end end
-- Update
function process( delta ) function process( delta )
if RL_IsMouseButtonDown( 0 ) then if RL_IsMouseButtonDown( 0 ) then
-- Create more bunnies -- Create more bunnies
@@ -69,8 +68,6 @@ function process( delta )
end end
end end
-- Draw
function draw() function draw()
RL_ClearBackground( RAYWHITE ) RL_ClearBackground( RAYWHITE )

View File

@@ -0,0 +1,112 @@
--[[
This example is translated from "raylib [shaders] example - Mesh instancing"
-- https://github.com/raysan5/raylib/blob/master/examples/shaders/shaders_mesh_instancing.c
Contributed by @seanpringle
Reviewed by Max (@moliad) and Ramon Santamaria (@raysan5)
Modified by Jussi Viitala (@nullstare) for ReiLua style.
]]
local MAX_INSTANCES = 10000
local cube
local transforms = {}
local camera
local shader
local matInstances
local matDefault
function init()
local monitor = 0
local mPos = RL_GetMonitorPosition( monitor )
local mSize = RL_GetMonitorSize( monitor )
local winSize = RL_GetWindowSize()
-- local winSize = { 1920, 1080 }
RL_SetWindowState( FLAG_WINDOW_RESIZABLE )
RL_SetWindowSize( winSize )
RL_SetWindowPosition( { mPos[1] + mSize[1] / 2 - winSize[1] / 2, mPos[2] + mSize[2] / 2 - winSize[2] / 2 } )
RL_SetWindowTitle( "Instancing" )
RL_SetWindowState( FLAG_VSYNC_HINT )
-- Define the camera to look into our 3d world
camera = RL_CreateCamera3D()
RL_SetCamera3DPosition( camera, { -125.0, 125.0, -125.0 } )
RL_SetCamera3DTarget( camera, { 0, 0, 0 } )
RL_SetCamera3DUp( camera, { 0, 1, 0 } )
RL_SetCamera3DFovy( camera, 45 )
RL_SetCameraMode( camera, CAMERA_ORBITAL )
-- Define mesh to be instanced
cube = RL_GenMeshCube( { 1, 1, 1 } )
-- Translate and rotate cubes randomly
for i = 1, MAX_INSTANCES do
local translation = RL_MatrixTranslate( { math.random( -50, 50 ), math.random( -50, 50 ), math.random( -50, 50 ) } )
local axis = RL_Vector3Normalize( { math.random( 0, 360 ), math.random( 0, 360 ), math.random( 0, 360 ) } )
local angle = math.rad( math.random( 0, 10 ) )
local rotation = RL_MatrixRotate( axis, angle )
table.insert( transforms, RL_MatrixMultiply( rotation, translation ) )
end
-- Load lighting shader
shader = RL_LoadShader( RL_GetBasePath().."../resources/shaders/glsl330/lighting_instancing.vs",
RL_GetBasePath().."../resources/shaders/glsl330/lighting.fs" )
-- Get shader locations
local mvpLoc = RL_GetShaderLocation( shader, "mvp" )
local viewPosLoc = RL_GetShaderLocation( shader, "viewPos" )
local instanceTransformLoc = RL_GetShaderLocationAttrib( shader, "instanceTransform" )
RL_SetShaderLocationIndex( shader, SHADER_LOC_MATRIX_MVP, mvpLoc )
RL_SetShaderLocationIndex( shader, SHADER_LOC_VECTOR_VIEW, viewPosLoc )
RL_SetShaderLocationIndex( shader, SHADER_LOC_MATRIX_MODEL, instanceTransformLoc )
-- Set shader value: ambient light level
local ambientLoc = RL_GetShaderLocation( shader, "ambient" )
RL_SetShaderValue( shader, ambientLoc, { 0.2, 0.2, 0.2, 0.1 }, SHADER_UNIFORM_VEC4 )
-- Create one light
RL_CreateLight( LIGHT_DIRECTIONAL, { 50.0, 50.0, 0.0 }, RL_Vector3Zero(), WHITE, shader )
-- NOTE: We are assigning the intancing shader to material.shader
-- to be used on mesh drawing with DrawMeshInstanced()
matInstances = RL_LoadMaterialDefault()
RL_SetMaterialShader( matInstances, shader )
RL_SetMaterialColor( matInstances, MATERIAL_MAP_DIFFUSE, RED )
-- Load default material (using raylib intenral default shader) for non-instanced mesh drawing
-- WARNING: Default shader enables vertex color attribute BUT GenMeshCube() does not generate vertex colors, so,
-- when drawing the color attribute is disabled and a default color value is provided as input for thevertex attribute
matDefault = RL_LoadMaterialDefault()
RL_SetMaterialColor( matDefault, MATERIAL_MAP_DIFFUSE, BLUE )
end
function process( delta )
RL_UpdateCamera3D( camera )
-- Update the light shader with the camera view position
local loc = RL_GetShaderLocationIndex( shader, SHADER_LOC_VECTOR_VIEW )
RL_SetShaderValue( shader, loc, RL_GetCamera3DPosition( camera ), SHADER_UNIFORM_VEC3 )
end
function draw()
RL_ClearBackground( DARKBLUE )
RL_BeginMode3D( camera )
-- Draw cube mesh with default material (BLUE)
RL_DrawMesh( cube, matDefault, RL_MatrixTranslate( { -10.0, 0.0, 0.0 } ) )
-- Draw meshes instanced using material containing instancing shader (RED + lighting),
-- transforms[] for the instances should be provided, they are dynamically
-- updated in GPU every frame, so we can animate the different mesh instances
RL_DrawMeshInstanced( cube, matInstances, transforms, MAX_INSTANCES )
-- Draw cube mesh with default material (BLUE)
RL_DrawMesh( cube, matDefault, RL_MatrixTranslate( { 10.0, 0.0, 0.0 } ) )
RL_EndMode3D()
RL_DrawFPS( { 10, 10 } )
end

View File

@@ -45,7 +45,7 @@ Gui = {
padding = 2, padding = 2,
spacing = 4, spacing = 4,
scrollbarWidth = 8, scrollbarWidth = 8,
scrollAmount = 10, scrollAmount = 20,
heldCallback = nil, heldCallback = nil,

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

View File

@@ -45,6 +45,7 @@ int lmodelsUnloadMaterial( lua_State *L );
int lmodelsSetMaterialTexture( lua_State *L ); int lmodelsSetMaterialTexture( lua_State *L );
int lmodelsSetMaterialColor( lua_State *L ); int lmodelsSetMaterialColor( lua_State *L );
int lmodelsSetMaterialValue( lua_State *L ); int lmodelsSetMaterialValue( lua_State *L );
int lmodelsSetMaterialShader( lua_State *L );
/* Model. */ /* Model. */
int lmodelsLoadModel( lua_State *L ); int lmodelsLoadModel( lua_State *L );
int lmodelsLoadModelFromMesh( lua_State *L ); int lmodelsLoadModelFromMesh( lua_State *L );

View File

@@ -1028,6 +1028,7 @@ void luaRegister() {
lua_register( L, "RL_SetMaterialTexture", lmodelsSetMaterialTexture ); lua_register( L, "RL_SetMaterialTexture", lmodelsSetMaterialTexture );
lua_register( L, "RL_SetMaterialColor", lmodelsSetMaterialColor ); lua_register( L, "RL_SetMaterialColor", lmodelsSetMaterialColor );
lua_register( L, "RL_SetMaterialValue", lmodelsSetMaterialValue ); lua_register( L, "RL_SetMaterialValue", lmodelsSetMaterialValue );
lua_register( L, "RL_SetMaterialShader", lmodelsSetMaterialShader );
/* Model. */ /* Model. */
lua_register( L, "RL_LoadModel", lmodelsLoadModel ); lua_register( L, "RL_LoadModel", lmodelsLoadModel );
lua_register( L, "RL_LoadModelFromMesh", lmodelsLoadModelFromMesh ); lua_register( L, "RL_LoadModelFromMesh", lmodelsLoadModelFromMesh );

View File

@@ -1287,12 +1287,10 @@ int lmodelsDrawMesh( lua_State *L ) {
return 1; return 1;
} }
/* TODO Untested. */
/* /*
> success = RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances ) > success = RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances )
Draw multiple mesh instances with material and different transforms Draw multiple mesh instances with material and different transforms
Note! Untested.
- Failure return false - Failure return false
- Success return true - Success return true
@@ -1305,14 +1303,14 @@ int lmodelsDrawMeshInstanced( lua_State *L ) {
} }
int instances = lua_tointeger( L, -1 ); int instances = lua_tointeger( L, -1 );
lua_pop( L, 1 ); lua_pop( L, 1 );
Matrix matrises[ instances ]; Matrix transforms[ instances ];
int t = lua_gettop( L ), i = 0; int t = lua_gettop( L ), i = 0;
lua_pushnil( L ); lua_pushnil( L );
while ( lua_next( L, t ) != 0 ) { while ( lua_next( L, t ) != 0 ) {
if ( lua_istable( L, -1 ) ) { if ( lua_istable( L, -1 ) ) {
matrises[i] = uluaGetMatrix( L ); transforms[i] = uluaGetMatrix( L );
} }
i++; i++;
lua_pop( L, 1 ); lua_pop( L, 1 );
@@ -1326,7 +1324,7 @@ int lmodelsDrawMeshInstanced( lua_State *L ) {
lua_pushboolean( L, false ); lua_pushboolean( L, false );
return 1; return 1;
} }
DrawMeshInstanced( *state->meshes[ meshId ], *state->materials[ materialId ], matrises, instances ); DrawMeshInstanced( *state->meshes[ meshId ], *state->materials[ materialId ], transforms, instances );
lua_pushboolean( L, true ); lua_pushboolean( L, true );
return 1; return 1;
@@ -1699,6 +1697,35 @@ int lmodelsSetMaterialValue( lua_State *L ) {
return 1; return 1;
} }
/*
> success = RL_SetMaterialShader( Material material, Shader shader )
Set shader for material
- Failure return false
- Success return true
*/
int lmodelsSetMaterialShader( lua_State *L ) {
if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMaterialShader( Material material, Shader shader )" );
lua_pushboolean( L, false );
return 1;
}
size_t shaderId = lua_tointeger( L, -1 );
lua_pop( L, 1 );
size_t materialId = lua_tointeger( L, -1 );
if ( !validMaterial( materialId || !validShader( shaderId ) ) ) {
lua_pushboolean( L, false );
return 1;
}
state->materials[ materialId ]->shader = *state->shaders[ shaderId ];
lua_pushboolean( L, true );
return 1;
}
/* /*
## Models - Model ## Models - Model
*/ */

View File

@@ -1607,7 +1607,7 @@ int lmathMatrixInvert( lua_State *L ) {
} }
/* /*
> result = MatrixIdentity() > result = RL_MatrixIdentity()
Get identity matrix Get identity matrix