diff options
| -rw-r--r-- | API.md | 46 | ||||
| -rw-r--r-- | devnotes | 2 | ||||
| -rw-r--r-- | doc_parser.lua | 1 | ||||
| -rw-r--r-- | include/core.h | 3 | ||||
| -rw-r--r-- | include/lights.h | 7 | ||||
| -rw-r--r-- | include/main.h | 2 | ||||
| -rw-r--r-- | include/rlights.h | 183 | ||||
| -rw-r--r-- | include/state.h | 4 | ||||
| -rw-r--r-- | src/core.c | 86 | ||||
| -rw-r--r-- | src/lights.c | 108 | ||||
| -rw-r--r-- | src/lua_core.c | 11 | ||||
| -rw-r--r-- | src/models.c | 2 | ||||
| -rw-r--r-- | src/state.c | 14 |
13 files changed, 458 insertions, 11 deletions
@@ -547,6 +547,12 @@ HUEBAR_SELECTOR_HEIGHT HUEBAR_SELECTOR_OVERFLOW +## Globals - LightType + +LIGHT_DIRECTIONAL + +LIGHT_POINT + ## Types Raylib structs in Lua @@ -1151,6 +1157,24 @@ Get shader attribute location --- +> success = RL_SetShaderLocationIndex( Shader shader, int shaderLocationIndex, int location ) + +Set shader location index + +- Failure return false +- Success return true + +--- + +> location = RL_GetShaderLocationIndex( Shader shader, int shaderLocationIndex ) + +Get shader location index + +- Failure return false +- Success return int + +--- + > success = RL_SetShaderValueMatrix( Shader shader, int locIndex, Matrix mat ) Set shader uniform value ( matrix 4x4 ) @@ -3953,3 +3977,25 @@ Check icon pixel value - Success return bool --- + +## Lights - Basics + +--- + +> light = RL_CreateLight( int type, Vector3 position, Vector3 target, Color color, Shader shader ) + +Create a light and get shader locations + +- Failure return -1 +- Success return int + +--- + +> success = RL_UpdateLightValues( Shader shader, Light light ) + +Send light properties to shader + +- Failure return false +- Success return true + +--- @@ -2,6 +2,7 @@ Current { } Backlog { + * Set reguirement for two arguments in Shader load functions. * More and better examples * Core @@ -13,6 +14,7 @@ Backlog { * String management. At least TextSplit. * Audio * Wave + * Raymath * Quaternions * Physac diff --git a/doc_parser.lua b/doc_parser.lua index 18fed00..19b69c9 100644 --- a/doc_parser.lua +++ b/doc_parser.lua @@ -142,6 +142,7 @@ local sourceFiles = { "src/audio.c", "src/rmath.c", "src/rgui.c", + "src/lights.c", } for _, src in ipairs( sourceFiles ) do diff --git a/include/core.h b/include/core.h index 1f0691c..8cb2977 100644 --- a/include/core.h +++ b/include/core.h @@ -2,6 +2,7 @@ /* Validators. */ bool validCamera3D( size_t id ); +bool validShader( size_t id ); /* Window. */ int lcoreIsWindowReady( lua_State *L ); int lcoreIsWindowFullscreen( lua_State *L ); @@ -61,6 +62,8 @@ int lcoreBeginShaderMode( lua_State *L ); int lcoreEndShaderMode( lua_State *L ); int lcoreGetShaderLocation( lua_State *L ); int lcoreGetShaderLocationAttrib( lua_State *L ); +int lcoreSetShaderLocationIndex( lua_State *L ); +int lcoreGetShaderLocationIndex( lua_State *L ); int lcoreSetShaderValueMatrix( lua_State *L ); int lcoreSetShaderValueTexture( lua_State *L ); int lcoreSetShaderValue( lua_State *L ); diff --git a/include/lights.h b/include/lights.h new file mode 100644 index 0000000..2b483b3 --- /dev/null +++ b/include/lights.h @@ -0,0 +1,7 @@ +#pragma once + +/* Validators. */ +bool validLight( size_t id ); +/* Basics. */ +int llightsCreateLight( lua_State *L ); +int llightsUpdateLightValues( lua_State *L ); diff --git a/include/main.h b/include/main.h index dd359ee..1f626f0 100644 --- a/include/main.h +++ b/include/main.h @@ -11,6 +11,8 @@ #include <string.h> #include "raylib.h" #include "raymath.h" +#include "raygui.h" +#include "rlights.h" #include "rlgl.h" #include <lua.h> #include <lualib.h> diff --git a/include/rlights.h b/include/rlights.h new file mode 100644 index 0000000..a1b2988 --- /dev/null +++ b/include/rlights.h @@ -0,0 +1,183 @@ +/********************************************************************************************** +* +* raylib.lights - Some useful functions to deal with lights data +* +* CONFIGURATION: +* +* #define RLIGHTS_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2017-2020 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#ifndef RLIGHTS_H +#define RLIGHTS_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 4 // Max dynamic lights supported by shader + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +// Light data +typedef struct { + int type; + Vector3 position; + Vector3 target; + Color color; + bool enabled; + + // Shader locations + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +// Light type +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader); // Create a light and get shader locations +void UpdateLightValues(Shader shader, Light light); // Send light properties to shader + +#ifdef __cplusplus +} +#endif + +#endif // RLIGHTS_H + + +/*********************************************************************************** +* +* RLIGHTS IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLIGHTS_IMPLEMENTATION) + +#include "raylib.h" + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static int lightsCount = 0; // Current amount of created lights + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Create a light and get shader locations +Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = position; + light.target = target; + light.color = color; + + // TODO: Below code doesn't look good to me, + // it assumes a specific shader naming and structure + // Probably this implementation could be improved + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + + // Set location name [x] depending on lights count + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + + lightsCount++; + } + + return light; +} + +// Send light properties to shader +// NOTE: Light shader locations should be available +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValue(shader, light.enabledLoc, &light.enabled, SHADER_UNIFORM_INT); + SetShaderValue(shader, light.typeLoc, &light.type, SHADER_UNIFORM_INT); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, SHADER_UNIFORM_VEC3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, SHADER_UNIFORM_VEC3); + + // Send to shader light color values + float color[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, + (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, color, SHADER_UNIFORM_VEC4); +} + +#endif // RLIGHTS_IMPLEMENTATION
\ No newline at end of file diff --git a/include/state.h b/include/state.h index 3fc4e8e..f724cc1 100644 --- a/include/state.h +++ b/include/state.h @@ -62,6 +62,10 @@ typedef struct { Shader **shaders; size_t shaderCount; size_t shaderAlloc; + /* Lights. */ + Light **lights; + size_t lightCount; + size_t lightAlloc; } State; extern State *state; @@ -44,7 +44,7 @@ bool validCamera3D( size_t id ) { } } -static inline bool validShader( size_t id ) { +bool validShader( size_t id ) { if ( id < 0 || state->shaderCount < id || state->shaders[ id ] == NULL ) { TraceLog( LOG_WARNING, "%s %d", "Invalid shader", id ); return false; @@ -859,8 +859,8 @@ int lcoreLoadShader( lua_State *L ) { } state->shaders[i] = malloc( sizeof( Shader ) ); // *state->shaders[i] = LoadShader( lua_tostring( L, -2 ), lua_tostring( L, -1 ) ); - // *state->shaders[i] = LoadShader( vsFileName, fsFileName ); - *state->shaders[i] = LoadShader( 0, fsFileName ); + *state->shaders[i] = LoadShader( vsFileName, fsFileName ); + // *state->shaders[i] = LoadShader( 0, fsFileName ); lua_pushinteger( L, i ); checkShaderRealloc( i ); @@ -876,13 +876,23 @@ Load shader from code strings and bind default locations - Success return int */ -//TODO Should also allow only one shader. int lcoreLoadShaderFromMemory( lua_State *L ) { - if ( !lua_isstring( L, -2 ) || !lua_isstring( L, -1 ) ) { - TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadShaderFromMemory( string vsCode, string fsCode )" ); - lua_pushinteger( L, -1 ); - return 1; + // if ( !lua_isstring( L, -2 ) || !lua_isstring( L, -1 ) ) { + // TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadShaderFromMemory( string vsCode, string fsCode )" ); + // lua_pushinteger( L, -1 ); + // return 1; + // } + + char fs[ STRING_LEN ] = { '\0' }; + char vs[ STRING_LEN ] = { '\0' }; + + if ( lua_isstring( L, -1 ) ) { + strcpy( fs, lua_tostring( L, -1 ) ); + } + if ( lua_isstring( L, -2 ) ) { + strcpy( vs, lua_tostring( L, -2 ) ); } + int i = 0; for ( i = 0; i < state->shaderCount; i++ ) { @@ -891,7 +901,8 @@ int lcoreLoadShaderFromMemory( lua_State *L ) { } } state->shaders[i] = malloc( sizeof( Shader ) ); - *state->shaders[i] = LoadShaderFromMemory( lua_tostring( L, -2 ), lua_tostring( L, -1 ) ); + // *state->shaders[i] = LoadShaderFromMemory( lua_tostring( L, -2 ), lua_tostring( L, -1 ) ); + *state->shaders[i] = LoadShaderFromMemory( vs, fs ); lua_pushinteger( L, i ); checkShaderRealloc( i ); @@ -986,6 +997,63 @@ int lcoreGetShaderLocationAttrib( lua_State *L ) { } /* +> success = RL_SetShaderLocationIndex( Shader shader, int shaderLocationIndex, int location ) + +Set shader location index + +- Failure return false +- Success return true +*/ +int lcoreSetShaderLocationIndex( lua_State *L ) { + if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetShaderLocationIndex( Shader shader, int shaderLocationIndex, int location )" ); + lua_pushboolean( L, false ); + return 1; + } + int location = lua_tointeger( L, -1 ); + lua_pop( L, 1 ); + int shaderLocationIndex = lua_tointeger( L, -1 ); + lua_pop( L, 1 ); + size_t shaderId = lua_tointeger( L, -1 ); + + if ( !validShader( shaderId ) ) { + lua_pushboolean( L, false ); + return 1; + } + state->shaders[ shaderId ]->locs[ shaderLocationIndex ] = location; + lua_pushboolean( L, true ); + + return 1; +} + +/* +> location = RL_GetShaderLocationIndex( Shader shader, int shaderLocationIndex ) + +Get shader location index + +- Failure return false +- Success return int +*/ +int lcoreGetShaderLocationIndex( lua_State *L ) { + if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetShaderLocationIndex( Shader shader, int shaderLocationIndex )" ); + lua_pushboolean( L, false ); + return 1; + } + int shaderLocationIndex = lua_tointeger( L, -1 ); + lua_pop( L, 1 ); + size_t shaderId = lua_tointeger( L, -1 ); + + if ( !validShader( shaderId ) ) { + lua_pushboolean( L, false ); + return 1; + } + lua_pushinteger( L, state->shaders[ shaderId ]->locs[ shaderLocationIndex ] ); + + return 1; +} + +/* > success = RL_SetShaderValueMatrix( Shader shader, int locIndex, Matrix mat ) Set shader uniform value ( matrix 4x4 ) diff --git a/src/lights.c b/src/lights.c new file mode 100644 index 0000000..381361e --- /dev/null +++ b/src/lights.c @@ -0,0 +1,108 @@ +#include "main.h" +#include "state.h" +#include "lua_core.h" +#include "core.h" +#include "lights.h" + +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +static void checkLightRealloc( int i ) { + if ( i == state->lightCount ) { + state->lightCount++; + } + + if ( state->lightCount == state->lightAlloc ) { + state->lightAlloc += ALLOC_PAGE_SIZE; + state->lights = realloc( state->lights, state->lightAlloc * sizeof( Light* ) ); + + for ( i = state->lightCount; i < state->lightAlloc; i++ ) { + state->lights[i] = NULL; + } + } +} + +bool validLight( size_t id ) { + if ( id < 0 || state->lightCount < id || state->lights[ id ] == NULL ) { + TraceLog( LOG_WARNING, "%s %d", "Invalid light", id ); + return false; + } + else { + return true; + } +} + +/* +## Lights - Basics +*/ + +/* +> light = RL_CreateLight( int type, Vector3 position, Vector3 target, Color color, Shader shader ) + +Create a light and get shader locations + +- Failure return -1 +- Success return int +*/ +int llightsCreateLight( lua_State *L ) { + if ( !lua_isnumber( L, -5 ) || !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CreateLight( int type, Vector3 position, Vector3 target, Color color, Shader shader )" ); + lua_pushinteger( L, -1 ); + return 1; + } + size_t shaderId = lua_tointeger( L, -1 ); + lua_pop( L, 1 ); + Color color = uluaGetColor( L ); + lua_pop( L, 1 ); + Vector3 target = uluaGetVector3( L ); + lua_pop( L, 1 ); + Vector3 position = uluaGetVector3( L ); + lua_pop( L, 1 ); + int type = lua_tointeger( L, -1 ); + + int i = 0; + + for ( i = 0; i < state->lightCount; i++ ) { + if ( state->lights[i] == NULL ) { + break; + } + } + state->lights[i] = malloc( sizeof( Light ) ); + *state->lights[i] = CreateLight( type, position, target, color, *state->shaders[ shaderId ] ); + lua_pushinteger( L, i ); + checkLightRealloc( i ); + + return 1; +} + +/* +> success = RL_UpdateLightValues( Shader shader, Light light ) + +Send light properties to shader + +- Failure return false +- Success return true +*/ +int llightsUpdateLightValues( lua_State *L ) { + if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) { + TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UpdateLightValues( Shader shader, Light light )" ); + lua_pushboolean( L, false ); + return 1; + } + size_t lightId = lua_tointeger( L, -1 ); + lua_pop( L, 1 ); + size_t shaderId = lua_tointeger( L, -1 ); + + if ( !validLight( lightId ) ) { + lua_pushboolean( L, false ); + return 1; + } + if ( !validShader( shaderId ) ) { + lua_pushboolean( L, false ); + return 1; + } + UpdateLightValues( *state->shaders[ shaderId ], *state->lights[ lightId ] ); + lua_pushboolean( L, true ); + + return 1; +} diff --git a/src/lua_core.c b/src/lua_core.c index 25cce86..09a4094 100644 --- a/src/lua_core.c +++ b/src/lua_core.c @@ -9,7 +9,7 @@ #include "audio.h" #include "rmath.h" #include "rgui.h" -#include "raygui.h" +#include "lights.h" static void assignGlobalInt( int value, const char *name ) { lua_State *L = state->luaState; @@ -289,6 +289,9 @@ void defineGlobals() { assignGlobalInt( HUEBAR_PADDING, "HUEBAR_PADDING" ); assignGlobalInt( HUEBAR_SELECTOR_HEIGHT, "HUEBAR_SELECTOR_HEIGHT" ); assignGlobalInt( HUEBAR_SELECTOR_OVERFLOW, "HUEBAR_SELECTOR_OVERFLOW" ); + /* LightType */ + assignGlobalInt( LIGHT_DIRECTIONAL, "LIGHT_DIRECTIONAL" ); + assignGlobalInt( LIGHT_POINT, "LIGHT_POINT" ); /*DOC_END*/ } @@ -530,6 +533,8 @@ void luaRegister() { lua_register( L, "RL_EndShaderMode", lcoreEndShaderMode ); lua_register( L, "RL_GetShaderLocation", lcoreGetShaderLocation ); lua_register( L, "RL_GetShaderLocationAttrib", lcoreGetShaderLocationAttrib ); + lua_register( L, "RL_SetShaderLocationIndex", lcoreSetShaderLocationIndex ); + lua_register( L, "RL_GetShaderLocationIndex", lcoreGetShaderLocationIndex ); lua_register( L, "RL_SetShaderValueMatrix", lcoreSetShaderValueMatrix ); lua_register( L, "RL_SetShaderValueTexture", lcoreSetShaderValueTexture ); lua_register( L, "RL_SetShaderValue", lcoreSetShaderValue ); @@ -879,6 +884,10 @@ void luaRegister() { lua_register( L, "RL_GuiSetIconPixel", lguiGuiSetIconPixel ); lua_register( L, "RL_GuiClearIconPixel", lguiGuiClearIconPixel ); lua_register( L, "RL_GuiCheckIconPixel", lguiGuiCheckIconPixel ); + /* Lights */ + /* Basics. */ + lua_register( L, "RL_CreateLight", llightsCreateLight ); + lua_register( L, "RL_UpdateLightValues", llightsUpdateLightValues ); } /* Lua util functions. */ diff --git a/src/models.c b/src/models.c index 483d0f8..3fe2e45 100644 --- a/src/models.c +++ b/src/models.c @@ -1321,7 +1321,7 @@ int lmodelsCreateMaterial( lua_State *L ) { } } else if ( strcmp( "shader", (char*)lua_tostring( L, -2 ) ) == 0 && lua_isnumber( L, -1 ) ) { - /* TODO Shader when implemented. */ + state->materials[i]->shader = *state->shaders[ lua_tointeger( L, -1 ) ]; } lua_pop( L, 1 ); } diff --git a/src/state.c b/src/state.c index d9b2ad4..cd7629b 100644 --- a/src/state.c +++ b/src/state.c @@ -61,6 +61,10 @@ bool stateInit( const char *exePath ) { state->shaderAlloc = ALLOC_PAGE_SIZE; state->shaderCount = 0; state->shaders = malloc( state->shaderAlloc * sizeof( Shader* ) ); + /* Lights. */ + state->lightAlloc = ALLOC_PAGE_SIZE; + state->lightCount = 0; + state->lights = malloc( state->lightAlloc * sizeof( Light* ) ); for ( int i = 0; i < ALLOC_PAGE_SIZE; i++ ) { state->images[i] = NULL; @@ -72,6 +76,7 @@ bool stateInit( const char *exePath ) { state->models[i] = NULL; state->animations[i] = NULL; state->shaders[i] = NULL; + state->lights[i] = NULL; /* The ones we want to save the first. */ if ( 0 < i ) { @@ -152,6 +157,9 @@ void stateFree() { } for ( int i = 0; i < state->materialCount; ++i ) { if ( state->materials[i] != NULL ) { + /* Prevent unloading shader that would result in double free when freeing shaders. */ + state->materials[i]->shader.id = rlGetShaderIdDefault(); + UnloadMaterial( *state->materials[i] ); free( state->materials[i] ); } @@ -168,6 +176,11 @@ void stateFree() { free( state->shaders[i] ); } } + for ( int i = 0; i < state->lightCount; ++i ) { + if ( state->lights[i] != NULL ) { + free( state->lights[i] ); + } + } if ( IsAudioDeviceReady() ) { CloseAudioDevice(); @@ -190,5 +203,6 @@ void stateFree() { free( state->models ); free( state->animations ); free( state->shaders ); + free( state->lights ); free( state ); } |
