13#include "nlua_shader.h"
42static int shader_compareUniform(
const void *a,
const void *b );
43static int shader_searchUniform(
const void *
id,
const void *u );
87 luaL_typerror( L, ind, SHADER_METATABLE );
101 luaL_getmetatable( L, SHADER_METATABLE );
102 lua_setmetatable( L, -2 );
116 if ( lua_getmetatable( L, ind ) == 0 )
118 lua_getfield( L, LUA_REGISTRYINDEX, SHADER_METATABLE );
121 if ( lua_rawequal( L, -1, -2 ) )
137 if ( shader->pp_id > 0 )
138 render_postprocessRm( shader->pp_id );
139 glDeleteProgram( shader->program );
141 free( shader->uniforms );
143 NLUA_ERROR( L, _(
"OpenGL Error!" ) );
160 lua_pushboolean( L, ( memcmp( f1, f2,
sizeof(
LuaShader_t ) ) == 0 ) );
167static int shader_compareUniform(
const void *a,
const void *b )
172 return strcmp( u1->name, u2->name );
175static int shader_searchUniform(
const void *
id,
const void *u )
177 return strcmp( (
const char *)
id, ( (
LuaUniform_t *)u )->name );
183 return bsearch( name, ls->uniforms, ls->nuniforms,
sizeof(
LuaUniform_t ),
184 shader_searchUniform );
198 const char *pixelcode, *vertexcode;
203 pixelcode = luaL_checkstring( L, 1 );
204 vertexcode = luaL_checkstring( L, 2 );
207 memset( &shader, 0,
sizeof( shader ) );
210 shader.program = gl_program_vert_frag_string(
211 vertexcode, strlen( vertexcode ), pixelcode, strlen( pixelcode ) );
212 if ( shader.program == 0 )
213 return NLUA_ERROR( L, _(
"shader failed to compile!" ) );
216#define ATTRIB( name ) \
217 shader.name = glGetAttribLocation( shader.program, #name )
218#define UNIFORM( name ) \
219 shader.name = glGetUniformLocation( shader.program, #name )
220 UNIFORM( ViewSpaceFromLocal );
221 UNIFORM( ClipSpaceFromView );
222 UNIFORM( ClipSpaceFromLocal );
223 UNIFORM( ViewNormalFromLocal );
225 UNIFORM( ConstantColour );
226 UNIFORM( love_ScreenSize );
227 ATTRIB( VertexPosition );
228 ATTRIB( VertexTexCoord );
229 ATTRIB( VertexColour );
234 glGetProgramiv( shader.program, GL_ACTIVE_UNIFORMS, &shader.nuniforms );
235 shader.uniforms = calloc( shader.nuniforms,
sizeof(
LuaUniform_t ) );
237 for ( GLint i = 0; i < shader.nuniforms; i++ ) {
239 glGetActiveUniform( shader.program, (GLuint)i, SHADER_NAME_MAXLEN,
240 &length, &u->size, &u->type, u->name );
241 u->id = glGetUniformLocation( shader.program, u->name );
245 if ( ( u->type == GL_SAMPLER_2D ) &&
246 ( strcmp( u->name,
"MainTex" ) != 0 ) ) {
247 if ( shader.tex == NULL )
251 t->active = GL_TEXTURE0 + ntex;
258 qsort( shader.uniforms, shader.nuniforms,
sizeof(
LuaUniform_t ),
259 shader_compareUniform );
262 NLUA_ERROR( L, _(
"OpenGL Error!" ) );
274 if ( lua_istable( L, idx ) ) {
275 for (
int j = 0; j < n; j++ ) {
276 lua_pushnumber( L, j + 1 );
277 lua_gettable( L, idx );
278 values[j] = luaL_checknumber( L, -1 );
282 for (
int j = 0; j < n; j++ )
283 values[j] = luaL_checknumber( L, idx + j );
292 if ( lua_istable( L, idx ) ) {
293 for (
int j = 0; j < n; j++ ) {
294 lua_pushnumber( L, j + 1 );
295 lua_gettable( L, idx );
296 values[j] = luaL_checkint( L, -1 );
300 for (
int j = 0; j < n; j++ )
301 values[j] = luaL_checkint( L, idx + j );
345 name = luaL_checkstring( L, 2 );
347 u = shader_getUniform( ls, name );
349 if ( ignore_missing )
351 return NLUA_ERROR( L, _(
"Shader does not have uniform '%s'!" ), name );
356 glUseProgram( ls->program );
361 glUniform1f( u->id, values[0] );
365 glUniform2f( u->id, values[0], values[1] );
369 glUniform3f( u->id, values[0], values[1], values[2] );
373 glUniform4f( u->id, values[0], values[1], values[2], values[3] );
378 glUniform1i( u->id, ivalues[0] );
382 glUniform2i( u->id, ivalues[0], ivalues[1] );
386 glUniform3i( u->id, ivalues[0], ivalues[1], ivalues[2] );
390 glUniform4i( u->id, ivalues[0], ivalues[1], ivalues[2], ivalues[3] );
395 ls->tex[u->tex].texid = tex->
texture;
400 _(
"Unsupported shader uniform type '%d' for uniform '%s'. "
407 NLUA_ERROR( L, _(
"OpenGL Error!" ) );
424 const char *name = luaL_checkstring( L, 2 );
427 lua_pushboolean( L, shader_getUniform( ls, name ) != NULL );
444 const char *str = luaL_optstring( L, 2,
"final" );
445 int priority = luaL_optinteger( L, 3, 0 );
446 int layer = PP_LAYER_FINAL;
448 if ( strcmp( str,
"final" ) == 0 )
449 layer = PP_LAYER_FINAL;
450 else if ( strcmp( str,
"game" ) == 0 )
451 layer = PP_LAYER_GAME;
452 else if ( strcmp( str,
"gui" ) == 0 )
453 layer = PP_LAYER_GUI;
454 else if ( strcmp( str,
"core" ) == 0 )
455 layer = PP_LAYER_CORE;
457 return NLUA_ERROR( L,
458 _(
"Layer was '%s', but must be one of 'final', "
459 "'game', 'gui', or 'core'." ),
462 if ( ls->
pp_id == 0 )
463 ls->
pp_id = render_postprocessAdd( ls, layer, priority, 0 );
464 lua_pushboolean( L, ls->
pp_id > 0 );
478 lua_pushboolean( L, render_postprocessRm( ls->
pp_id ) );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
LuaShader_t * lua_pushshader(lua_State *L, LuaShader_t shader)
Pushes a shader on the stack.
void shader_parseUniformArgsFloat(GLfloat values[4], lua_State *L, int idx, int n)
Helper to parse up float vector (or arguments).
static int shaderL_send(lua_State *L)
Allows setting values of uniforms for a shader. Errors out if the uniform is unknown or unused (as in...
static int shaderL_sendRaw(lua_State *L)
Allows setting values of uniforms for a shader, while ignoring unknown (or unused) uniforms.
void shader_parseUniformArgsInt(GLint values[4], lua_State *L, int idx, int n)
Helper to parse up integer vector (or arguments).
static const luaL_Reg shaderL_methods[]
static int shaderL_eq(lua_State *L)
Compares two shaders to see if they are the same.
static int shaderL_new(lua_State *L)
Creates a new shader.
static int shaderL_hasUniform(lua_State *L)
Checks to see if a shader has a uniform.
static int shaderL_addPostProcess(lua_State *L)
Sets a shader as a post-processing shader.
LuaShader_t * lua_toshader(lua_State *L, int ind)
Lua bindings to interact with shaders.
int nlua_loadShader(nlua_env env)
Loads the shader library.
LuaShader_t * luaL_checkshader(lua_State *L, int ind)
Gets shader at index or raises error if there is no shader at index.
static int shaderL_rmPostProcess(lua_State *L)
Removes a shader as a post-processing shader.
static int shaderL_sendHelper(lua_State *L, int ignore_missing)
Helper to set the uniform while handling unknown/inactive uniforms.
int lua_isshader(lua_State *L, int ind)
Checks to see if ind is a shader.
static int shaderL_gc(lua_State *L)
Frees a shader.
glTexture * luaL_checktex(lua_State *L, int ind)
Gets texture at index or raises error if there is no texture at index.
Abstraction for rendering sprite sheets.