diff --git a/src/rlgl.c b/src/rlgl.c index 8d230550f..3dda77b16 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -62,6 +62,10 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()] #endif +#if !defined(GRAPHICS_API_OPENGL_11) + #include "standard_shader.h" // Standard shader to embed +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -189,26 +193,27 @@ static bool useTempBuffer = false; // Shader Programs static Shader defaultShader; -static Shader standardShader; -static Shader currentShader; // By default, defaultShader +static Shader standardShader; // Lazy initialization when GetStandardShader() +static Shader currentShader; // By default, defaultShader +static bool standardShaderLoaded = false; // Flags for supported extensions -static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension) +static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension) // Compressed textures support flags -static bool texCompETC1Supported = false; // ETC1 texture compression support -static bool texCompETC2Supported = false; // ETC2/EAC texture compression support -static bool texCompPVRTSupported = false; // PVR texture compression support -static bool texCompASTCSupported = false; // ASTC texture compression support +static bool texCompETC1Supported = false; // ETC1 texture compression support +static bool texCompETC2Supported = false; // ETC2/EAC texture compression support +static bool texCompPVRTSupported = false; // PVR texture compression support +static bool texCompASTCSupported = false; // ASTC texture compression support // Lighting data -static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount; // Counts current enabled physic objects +static Light lights[MAX_LIGHTS]; // Lights pool +static int lightsCount; // Counts current enabled physic objects #endif // Compressed textures support flags -static bool texCompDXTSupported = false; // DDS texture compression support -static bool npotSupported = false; // NPOT textures full support +static bool texCompDXTSupported = false; // DDS texture compression support +static bool npotSupported = false; // NPOT textures full support #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: VAO functionality is exposed through extensions (OES) @@ -1031,7 +1036,6 @@ void rlglInit(void) // Init default Shader (customized for GL 3.3 and ES2) defaultShader = LoadDefaultShader(); - standardShader = LoadStandardShader(); currentShader = defaultShader; LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads) @@ -2184,14 +2188,22 @@ Shader GetDefaultShader(void) } // Get default shader +// NOTE: Inits global variable standardShader Shader GetStandardShader(void) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return standardShader; -#else Shader shader = { 0 }; - return shader; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + if (standardShaderLoaded) shader = standardShader; + else + { + // Lazy initialization of standard shader + standardShader = LoadStandardShader(); + shader = standardShader; + } #endif + + return shader; } // Get shader uniform location @@ -2567,18 +2579,22 @@ static Shader LoadDefaultShader(void) // Load standard shader // NOTE: This shader supports: -// - Up to 3 different maps: diffuse, normal, specular -// - Material properties: colAmbient, colDiffuse, colSpecular, glossiness -// - Up to 8 lights: Point, Directional or Spot +// - Up to 3 different maps: diffuse, normal, specular +// - Material properties: colAmbient, colDiffuse, colSpecular, glossiness +// - Up to 8 lights: Point, Directional or Spot static Shader LoadStandardShader(void) { - // Load standard shader (TODO: rewrite as char pointers) - Shader shader = LoadShader("resources/shaders/standard.vs", "resources/shaders/standard.fs"); + Shader shader; + + // Load standard shader (embeded in standard_shader.h) + shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr); if (shader.id != 0) { LoadDefaultShaderLocations(&shader); TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id); + + standardShaderLoaded = true; } else { diff --git a/src/standard_shader.h b/src/standard_shader.h new file mode 100644 index 000000000..956b5c32c --- /dev/null +++ b/src/standard_shader.h @@ -0,0 +1,166 @@ + +// Vertex shader definition to embed, no external file required +const static unsigned char vStandardShaderStr[] = +#if defined(GRAPHICS_API_OPENGL_21) +"#version 120 \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) +"#version 100 \n" +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +"attribute vec3 vertexPosition; \n" +"attribute vec3 vertexNormal; \n" +"attribute vec2 vertexTexCoord; \n" +"attribute vec4 vertexColor; \n" +"varying vec3 fragPosition; \n" +"varying vec3 fragNormal; \n" +"varying vec2 fragTexCoord; \n" +"varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) +"#version 330 \n" +"in vec3 vertexPosition; \n" +"in vec3 vertexNormal; \n" +"in vec2 vertexTexCoord; \n" +"in vec4 vertexColor; \n" +"out vec3 fragPosition; \n" +"out vec3 fragNormal; \n" +"out vec2 fragTexCoord; \n" +"out vec4 fragColor; \n" +#endif +"uniform mat4 mvpMatrix; \n" +"void main() \n" +"{ \n" +" fragPosition = vertexPosition; \n" +" fragNormal = vertexNormal; \n" +" fragTexCoord = vertexTexCoord; \n" +" fragColor = vertexColor; \n" +" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" +"} \n"; + +// Fragment shader definition to embed, no external file required +const static unsigned char fStandardShaderStr[] = +#if defined(GRAPHICS_API_OPENGL_21) +"#version 120 \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) +"#version 100 \n" +"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +"varying vec3 fragPosition; \n" +"varying vec3 fragNormal; \n" +"varying vec2 fragTexCoord; \n" +"varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) +"#version 330 \n" +"in vec3 fragPosition; \n" +"in vec3 fragNormal; \n" +"in vec2 fragTexCoord; \n" +"in vec4 fragColor; \n" +"out vec4 finalColor; \n" +#endif +"uniform sampler2D texture0; \n" +"uniform sampler2D texture1; \n" +"uniform sampler2D texture2; \n" +"uniform vec4 colAmbient; \n" +"uniform vec4 colDiffuse; \n" +"uniform vec4 colSpecular; \n" +"uniform float glossiness; \n" +"uniform int useNormal; \n" +"uniform int useSpecular; \n" +"uniform mat4 modelMatrix; \n" +"uniform vec3 viewDir; \n" +"struct Light { \n" +" int enabled; \n" +" int type; \n" +" vec3 position; \n" +" vec3 direction; \n" +" vec4 diffuse; \n" +" float intensity; \n" +" float radius; \n" +" float coneAngle; }; \n" +"const int maxLights = 8; \n" +"uniform int lightsCount; \n" +"uniform Light lights[maxLights]; \n" +"\n" +"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" +"{\n" +" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" +" vec3 surfaceToLight = l.position - surfacePos;\n" +" float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);\n" +" float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;\n" +" float spec = 0.0;\n" +" if (diff > 0.0)\n" +" {\n" +" vec3 h = normalize(-l.direction + v);\n" +" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" }\n" +" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" +"}\n" +"\n" +"vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n" +"{\n" +" vec3 lightDir = normalize(-l.direction);\n" +" float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;\n" +" float spec = 0.0;\n" +" if (diff > 0.0)\n" +" {\n" +" vec3 h = normalize(lightDir + v);\n" +" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" }\n" +" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" +"}\n" +"\n" +"vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)\n" +"{\n" +" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" +" vec3 lightToSurface = normalize(surfacePos - l.position);\n" +" vec3 lightDir = normalize(-l.direction);\n" +" float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;\n" +" float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);\n" +" attenuation = dot(lightToSurface, -lightDir);\n" +" float lightToSurfaceAngle = degrees(acos(attenuation));\n" +" if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;\n" +" float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;\n" +" float diffAttenuation = diff*attenuation;\n" +" float spec = 0.0;\n" +" if (diffAttenuation > 0.0)\n" +" {\n" +" vec3 h = normalize(lightDir + v);\n" +" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" }\n" +" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));\n" +" vec3 normal = normalize(normalMatrix*fragNormal);\n" +" vec3 n = normalize(normal);\n" +" vec3 v = normalize(viewDir);\n" +" vec4 texelColor = texture(texture0, fragTexCoord);\n" +" vec3 lighting = colAmbient.rgb;\n" +" if (useNormal == 1)\n" +" {\n" +" n *= texture(texture1, fragTexCoord).rgb;\n" +" n = normalize(n);\n" +" }\n" +" float spec = 1.0;\n" +" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" +" for (int i = 0; i < lightsCount; i++)\n" +" {\n" +" if (lights[i].enabled == 1)\n" +" {\n" +" switch (lights[i].type)\n" +" {\n" +" case 0: lighting += CalcPointLight(lights[i], n, v, spec); break;\n" +" case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break;\n" +" case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break;\n" +" default: break;\n" +" }\n" +" }\n" +" }\n" +#if defined(GRAPHICS_API_OPENGL_33) +" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" +#endif +"} \n"; \ No newline at end of file