Move lighting system out of raylib
Lighting is implemented as a raylib example now
This commit is contained in:
parent
7b5f61ddf7
commit
37a64df7b9
5 changed files with 366 additions and 522 deletions
|
@ -9,15 +9,79 @@
|
||||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||||
*
|
*
|
||||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
* This example has been created using raylib 1.7 (www.raylib.com)
|
||||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2016-2017 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: NULL
|
||||||
|
#include <string.h> // Required for: strcpy()
|
||||||
|
#include <math.h> // Required for: vector math
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define MAX_LIGHTS 8 // Max lights supported by standard shader
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Light type
|
||||||
|
typedef struct LightData {
|
||||||
|
unsigned int id; // Light unique id
|
||||||
|
bool enabled; // Light enabled
|
||||||
|
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
|
||||||
|
|
||||||
|
Vector3 position; // Light position
|
||||||
|
Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
|
||||||
|
float radius; // Light attenuation radius light intensity reduced with distance (world distance)
|
||||||
|
|
||||||
|
Color diffuse; // Light diffuse color
|
||||||
|
float intensity; // Light intensity level
|
||||||
|
|
||||||
|
float coneAngle; // Light cone max angle: LIGHT_SPOT
|
||||||
|
} LightData, *Light;
|
||||||
|
|
||||||
|
// Light types
|
||||||
|
typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static Light lights[MAX_LIGHTS]; // Lights pool
|
||||||
|
static int lightsCount = 0; // Enabled lights counter
|
||||||
|
static int lightsLocs[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light:
|
||||||
|
// enabled, type, position, target, radius, diffuse, intensity, coneAngle
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
|
||||||
|
static void DestroyLight(Light light); // Destroy a light and take it out of the list
|
||||||
|
static void DrawLight(Light light); // Draw light in 3D world
|
||||||
|
|
||||||
|
static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS)
|
||||||
|
static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights
|
||||||
|
|
||||||
|
// Vector3 math functions
|
||||||
|
static float VectorLength(const Vector3 v); // Calculate vector lenght
|
||||||
|
static void VectorNormalize(Vector3 *v); // Normalize provided vector
|
||||||
|
static Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors
|
||||||
|
|
||||||
|
|
||||||
|
//https://www.gamedev.net/topic/655969-speed-gluniform-vs-uniform-buffer-objects/
|
||||||
|
//https://www.reddit.com/r/opengl/comments/4ri20g/is_gluniform_more_expensive_than_glprogramuniform/
|
||||||
|
//http://cg.alexandra.dk/?p=3778 - AZDO
|
||||||
|
//https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
|
@ -39,6 +103,9 @@ int main()
|
||||||
|
|
||||||
material.shader = LoadShader("resources/shaders/glsl330/standard.vs", "resources/shaders/glsl330/standard.fs");
|
material.shader = LoadShader("resources/shaders/glsl330/standard.vs", "resources/shaders/glsl330/standard.fs");
|
||||||
|
|
||||||
|
// Try to get lights location points (if available)
|
||||||
|
GetShaderLightsLocations(material.shader);
|
||||||
|
|
||||||
material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture
|
material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture
|
||||||
material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture
|
material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture
|
||||||
material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture
|
material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture
|
||||||
|
@ -65,6 +132,12 @@ int main()
|
||||||
pointLight->diffuse = (Color){100, 100, 255, 255};
|
pointLight->diffuse = (Color){100, 100, 255, 255};
|
||||||
pointLight->radius = 3.0f;
|
pointLight->radius = 3.0f;
|
||||||
|
|
||||||
|
// Set shader lights values for enabled lights
|
||||||
|
// NOTE: If values are not changed in real time, they can be set at initialization!!!
|
||||||
|
SetShaderLightsValues(material.shader);
|
||||||
|
|
||||||
|
//SetShaderActive(0);
|
||||||
|
|
||||||
// Setup orbital camera
|
// Setup orbital camera
|
||||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||||
|
|
||||||
|
@ -115,8 +188,295 @@ int main()
|
||||||
DestroyLight(dirLight);
|
DestroyLight(dirLight);
|
||||||
DestroyLight(spotLight);
|
DestroyLight(spotLight);
|
||||||
|
|
||||||
|
// Unload lights
|
||||||
|
if (lightsCount > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < lightsCount; i++) free(lights[i]);
|
||||||
|
lightsCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definitions
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create a new light, initialize it and add to pool
|
||||||
|
Light CreateLight(int type, Vector3 position, Color diffuse)
|
||||||
|
{
|
||||||
|
Light light = NULL;
|
||||||
|
|
||||||
|
if (lightsCount < MAX_LIGHTS)
|
||||||
|
{
|
||||||
|
// Allocate dynamic memory
|
||||||
|
light = (Light)malloc(sizeof(LightData));
|
||||||
|
|
||||||
|
// Initialize light values with generic values
|
||||||
|
light->id = lightsCount;
|
||||||
|
light->type = type;
|
||||||
|
light->enabled = true;
|
||||||
|
|
||||||
|
light->position = position;
|
||||||
|
light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||||
|
light->intensity = 1.0f;
|
||||||
|
light->diffuse = diffuse;
|
||||||
|
|
||||||
|
// Add new light to the array
|
||||||
|
lights[lightsCount] = light;
|
||||||
|
|
||||||
|
// Increase enabled lights count
|
||||||
|
lightsCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: Returning latest created light to avoid crashes
|
||||||
|
light = lights[lightsCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a light and take it out of the list
|
||||||
|
void DestroyLight(Light light)
|
||||||
|
{
|
||||||
|
if (light != NULL)
|
||||||
|
{
|
||||||
|
int lightId = light->id;
|
||||||
|
|
||||||
|
// Free dynamic memory allocation
|
||||||
|
free(lights[lightId]);
|
||||||
|
|
||||||
|
// Remove *obj from the pointers array
|
||||||
|
for (int i = lightId; i < lightsCount; i++)
|
||||||
|
{
|
||||||
|
// Resort all the following pointers of the array
|
||||||
|
if ((i + 1) < lightsCount)
|
||||||
|
{
|
||||||
|
lights[i] = lights[i + 1];
|
||||||
|
lights[i]->id = lights[i + 1]->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrease enabled physic objects count
|
||||||
|
lightsCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw light in 3D world
|
||||||
|
void DrawLight(Light light)
|
||||||
|
{
|
||||||
|
switch (light->type)
|
||||||
|
{
|
||||||
|
case LIGHT_POINT:
|
||||||
|
{
|
||||||
|
DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
|
||||||
|
DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
} break;
|
||||||
|
case LIGHT_DIRECTIONAL:
|
||||||
|
{
|
||||||
|
DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
|
||||||
|
DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
} break;
|
||||||
|
case LIGHT_SPOT:
|
||||||
|
{
|
||||||
|
DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
|
||||||
|
Vector3 dir = VectorSubtract(light->target, light->position);
|
||||||
|
VectorNormalize(&dir);
|
||||||
|
|
||||||
|
DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
|
||||||
|
//DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY));
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get shader locations for lights (up to MAX_LIGHTS)
|
||||||
|
static void GetShaderLightsLocations(Shader shader)
|
||||||
|
{
|
||||||
|
char locName[32] = "lights[x].\0";
|
||||||
|
char locNameUpdated[64];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
{
|
||||||
|
locName[7] = '0' + i;
|
||||||
|
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "enabled\0");
|
||||||
|
lightsLocs[i][0] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "type\0");
|
||||||
|
lightsLocs[i][1] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "position\0");
|
||||||
|
lightsLocs[i][2] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "direction\0");
|
||||||
|
lightsLocs[i][3] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "radius\0");
|
||||||
|
lightsLocs[i][4] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "diffuse\0");
|
||||||
|
lightsLocs[i][5] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "intensity\0");
|
||||||
|
lightsLocs[i][6] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
|
||||||
|
locNameUpdated[0] = '\0';
|
||||||
|
strcpy(locNameUpdated, locName);
|
||||||
|
strcat(locNameUpdated, "coneAngle\0");
|
||||||
|
lightsLocs[i][7] = GetShaderLocation(shader, locNameUpdated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set shader uniform values for lights
|
||||||
|
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0
|
||||||
|
// TODO: Replace glUniform1i(), glUniform1f(), glUniform3f(), glUniform4f():
|
||||||
|
//SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
|
||||||
|
//SetShaderValuei(Shader shader, int uniformLoc, int *value, int size)
|
||||||
|
static void SetShaderLightsValues(Shader shader)
|
||||||
|
{
|
||||||
|
int tempInt[8] = { 0 };
|
||||||
|
float tempFloat[8] = { 0.0f };
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
{
|
||||||
|
if (i < lightsCount)
|
||||||
|
{
|
||||||
|
tempInt[0] = lights[i]->enabled;
|
||||||
|
SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], lights[i]->enabled);
|
||||||
|
|
||||||
|
tempInt[0] = lights[i]->type;
|
||||||
|
SetShaderValuei(shader, lightsLocs[i][1], tempInt, 1); //glUniform1i(lightsLocs[i][1], lights[i]->type);
|
||||||
|
|
||||||
|
tempFloat[0] = (float)lights[i]->diffuse.r/255.0f;
|
||||||
|
tempFloat[1] = (float)lights[i]->diffuse.g/255.0f;
|
||||||
|
tempFloat[2] = (float)lights[i]->diffuse.b/255.0f;
|
||||||
|
tempFloat[3] = (float)lights[i]->diffuse.a/255.0f;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][5], tempFloat, 4);
|
||||||
|
//glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255);
|
||||||
|
|
||||||
|
tempFloat[0] = lights[i]->intensity;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][6], tempFloat, 1);
|
||||||
|
|
||||||
|
switch (lights[i]->type)
|
||||||
|
{
|
||||||
|
case LIGHT_POINT:
|
||||||
|
{
|
||||||
|
tempFloat[0] = lights[i]->position.x;
|
||||||
|
tempFloat[1] = lights[i]->position.y;
|
||||||
|
tempFloat[2] = lights[i]->position.z;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3);
|
||||||
|
|
||||||
|
tempFloat[0] = lights[i]->radius;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][4], tempFloat, 1);
|
||||||
|
|
||||||
|
//glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
|
||||||
|
//glUniform1f(lightsLocs[i][4], lights[i]->radius);
|
||||||
|
} break;
|
||||||
|
case LIGHT_DIRECTIONAL:
|
||||||
|
{
|
||||||
|
Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position);
|
||||||
|
VectorNormalize(&direction);
|
||||||
|
|
||||||
|
tempFloat[0] = direction.x;
|
||||||
|
tempFloat[1] = direction.y;
|
||||||
|
tempFloat[2] = direction.z;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3);
|
||||||
|
|
||||||
|
//glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
|
||||||
|
} break;
|
||||||
|
case LIGHT_SPOT:
|
||||||
|
{
|
||||||
|
tempFloat[0] = lights[i]->position.x;
|
||||||
|
tempFloat[1] = lights[i]->position.y;
|
||||||
|
tempFloat[2] = lights[i]->position.z;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3);
|
||||||
|
|
||||||
|
//glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
|
||||||
|
|
||||||
|
Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position);
|
||||||
|
VectorNormalize(&direction);
|
||||||
|
|
||||||
|
tempFloat[0] = direction.x;
|
||||||
|
tempFloat[1] = direction.y;
|
||||||
|
tempFloat[2] = direction.z;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3);
|
||||||
|
//glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
|
||||||
|
|
||||||
|
tempFloat[0] = lights[i]->coneAngle;
|
||||||
|
SetShaderValue(shader, lightsLocs[i][7], tempFloat, 1);
|
||||||
|
//glUniform1f(lightsLocs[i][7], lights[i]->coneAngle);
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempInt[0] = 0;
|
||||||
|
SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], 0); // Light disabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate vector lenght
|
||||||
|
float VectorLength(const Vector3 v)
|
||||||
|
{
|
||||||
|
float length;
|
||||||
|
|
||||||
|
length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize provided vector
|
||||||
|
void VectorNormalize(Vector3 *v)
|
||||||
|
{
|
||||||
|
float length, ilength;
|
||||||
|
|
||||||
|
length = VectorLength(*v);
|
||||||
|
|
||||||
|
if (length == 0.0f) length = 1.0f;
|
||||||
|
|
||||||
|
ilength = 1.0f/length;
|
||||||
|
|
||||||
|
v->x *= ilength;
|
||||||
|
v->y *= ilength;
|
||||||
|
v->z *= ilength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substract two vectors
|
||||||
|
Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result;
|
||||||
|
|
||||||
|
result.x = v1.x - v2.x;
|
||||||
|
result.y = v1.y - v2.y;
|
||||||
|
result.z = v1.z - v2.z;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
48
src/models.c
48
src/models.c
|
@ -574,43 +574,6 @@ void DrawGizmo(Vector3 position)
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Draw light in 3D world
|
|
||||||
void DrawLight(Light light)
|
|
||||||
{
|
|
||||||
switch (light->type)
|
|
||||||
{
|
|
||||||
case LIGHT_POINT:
|
|
||||||
{
|
|
||||||
DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
|
|
||||||
DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
} break;
|
|
||||||
case LIGHT_DIRECTIONAL:
|
|
||||||
{
|
|
||||||
DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
|
|
||||||
DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
} break;
|
|
||||||
case LIGHT_SPOT:
|
|
||||||
{
|
|
||||||
DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
|
|
||||||
Vector3 dir = VectorSubtract(light->target, light->position);
|
|
||||||
VectorNormalize(&dir);
|
|
||||||
|
|
||||||
DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
|
|
||||||
//DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY));
|
|
||||||
} break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load mesh from file
|
// Load mesh from file
|
||||||
Mesh LoadMesh(const char *fileName)
|
Mesh LoadMesh(const char *fileName)
|
||||||
{
|
{
|
||||||
|
@ -751,17 +714,6 @@ Material LoadDefaultMaterial(void)
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load standard material (uses material attributes and lighting shader)
|
|
||||||
// NOTE: Standard shader supports multiple maps and lights
|
|
||||||
Material LoadStandardMaterial(void)
|
|
||||||
{
|
|
||||||
Material material = LoadDefaultMaterial();
|
|
||||||
|
|
||||||
material.shader = GetStandardShader();
|
|
||||||
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload material from memory
|
// Unload material from memory
|
||||||
void UnloadMaterial(Material material)
|
void UnloadMaterial(Material material)
|
||||||
{
|
{
|
||||||
|
|
26
src/raylib.h
26
src/raylib.h
|
@ -12,7 +12,6 @@
|
||||||
* Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF)
|
* Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF)
|
||||||
* Multiple textures support, including compressed formats and mipmaps generation
|
* Multiple textures support, including compressed formats and mipmaps generation
|
||||||
* Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
|
* Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
|
||||||
* Materials (diffuse, normal, specular) and Lighting (point, directional, spot) support
|
|
||||||
* Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
|
* Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
|
||||||
* Audio loading and playing with streaming support and mixing channels [audio]
|
* Audio loading and playing with streaming support and mixing channels [audio]
|
||||||
* VR stereo rendering support with configurable HMD device parameters
|
* VR stereo rendering support with configurable HMD device parameters
|
||||||
|
@ -466,25 +465,6 @@ typedef struct Model {
|
||||||
Material material; // Shader and textures data
|
Material material; // Shader and textures data
|
||||||
} Model;
|
} Model;
|
||||||
|
|
||||||
// Light type
|
|
||||||
typedef struct LightData {
|
|
||||||
unsigned int id; // Light unique id
|
|
||||||
bool enabled; // Light enabled
|
|
||||||
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
|
|
||||||
|
|
||||||
Vector3 position; // Light position
|
|
||||||
Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
|
|
||||||
float radius; // Light attenuation radius light intensity reduced with distance (world distance)
|
|
||||||
|
|
||||||
Color diffuse; // Light diffuse color
|
|
||||||
float intensity; // Light intensity level
|
|
||||||
|
|
||||||
float coneAngle; // Light cone max angle: LIGHT_SPOT
|
|
||||||
} LightData, *Light;
|
|
||||||
|
|
||||||
// Light types
|
|
||||||
typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
|
|
||||||
|
|
||||||
// Ray type (useful for raycast)
|
// Ray type (useful for raycast)
|
||||||
typedef struct Ray {
|
typedef struct Ray {
|
||||||
Vector3 position; // Ray position (origin)
|
Vector3 position; // Ray position (origin)
|
||||||
|
@ -876,7 +856,6 @@ RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color);
|
||||||
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
|
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
|
||||||
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
||||||
RLAPI void DrawGizmo(Vector3 position); // Draw simple gizmo
|
RLAPI void DrawGizmo(Vector3 position); // Draw simple gizmo
|
||||||
RLAPI void DrawLight(Light light); // Draw light in 3D world
|
|
||||||
//DrawTorus(), DrawTeapot() could be useful?
|
//DrawTorus(), DrawTeapot() could be useful?
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
@ -894,7 +873,6 @@ RLAPI void UnloadModel(Model model);
|
||||||
RLAPI Material LoadMaterial(const char *fileName); // Load material from file
|
RLAPI Material LoadMaterial(const char *fileName); // Load material from file
|
||||||
RLAPI Material LoadMaterialEx(Shader shader, Texture2D diffuse, Color color); // Load material from basic shading data
|
RLAPI Material LoadMaterialEx(Shader shader, Texture2D diffuse, Color color); // Load material from basic shading data
|
||||||
RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
|
RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
|
||||||
RLAPI Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader)
|
|
||||||
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
|
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
|
||||||
|
|
||||||
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
|
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
|
||||||
|
@ -930,7 +908,6 @@ RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Loa
|
||||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
RLAPI Shader GetDefaultShader(void); // Get default shader
|
RLAPI Shader GetDefaultShader(void); // Get default shader
|
||||||
RLAPI Shader GetStandardShader(void); // Get standard shader
|
|
||||||
RLAPI Texture2D GetDefaultTexture(void); // Get default texture
|
RLAPI Texture2D GetDefaultTexture(void); // Get default texture
|
||||||
|
|
||||||
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||||
|
@ -946,9 +923,6 @@ RLAPI void EndShaderMode(void); // End
|
||||||
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||||
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||||
|
|
||||||
RLAPI Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
|
|
||||||
RLAPI void DestroyLight(Light light); // Destroy a light and take it out of the list
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// VR experience Functions (Module: rlgl)
|
// VR experience Functions (Module: rlgl)
|
||||||
// NOTE: This functions are useless when using OpenGL 1.1
|
// NOTE: This functions are useless when using OpenGL 1.1
|
||||||
|
|
275
src/rlgl.c
275
src/rlgl.c
|
@ -22,7 +22,6 @@
|
||||||
* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend
|
* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend
|
||||||
*
|
*
|
||||||
* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency)
|
* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency)
|
||||||
* RLGL_NO_STANDARD_SHADER - Avoid standard shader (shader_standard.h) inclusion
|
|
||||||
* RLGL_NO_DISTORTION_SHADER - Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion
|
* RLGL_NO_DISTORTION_SHADER - Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion
|
||||||
* RLGL_OCULUS_SUPPORT - Enable Oculus Rift CV1 functionality
|
* RLGL_OCULUS_SUPPORT - Enable Oculus Rift CV1 functionality
|
||||||
*
|
*
|
||||||
|
@ -92,10 +91,6 @@
|
||||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
|
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_STANDARD_SHADER)
|
|
||||||
#include "shader_standard.h" // Standard shader to be embedded
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER)
|
#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER)
|
||||||
#include "shader_distortion.h" // Distortion shader to be embedded
|
#include "shader_distortion.h" // Distortion shader to be embedded
|
||||||
#endif
|
#endif
|
||||||
|
@ -119,8 +114,6 @@
|
||||||
#define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations)
|
#define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations)
|
||||||
// NOTE: Every vertex are 3 floats (12 bytes)
|
// NOTE: Every vertex are 3 floats (12 bytes)
|
||||||
|
|
||||||
#define MAX_LIGHTS 8 // Max lights supported by standard shader
|
|
||||||
|
|
||||||
#ifndef GL_SHADING_LANGUAGE_VERSION
|
#ifndef GL_SHADING_LANGUAGE_VERSION
|
||||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||||
#endif
|
#endif
|
||||||
|
@ -305,10 +298,7 @@ static bool useTempBuffer = false;
|
||||||
|
|
||||||
// Shader Programs
|
// Shader Programs
|
||||||
static Shader defaultShader; // Basic shader, support vertex color and diffuse texture
|
static Shader defaultShader; // Basic shader, support vertex color and diffuse texture
|
||||||
static Shader standardShader; // Shader with support for lighting and materials
|
|
||||||
// NOTE: Lazy initialization when GetStandardShader()
|
|
||||||
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
|
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
|
||||||
static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded
|
|
||||||
|
|
||||||
// Extension supported flag: VAO
|
// Extension supported flag: VAO
|
||||||
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)
|
||||||
|
@ -368,12 +358,6 @@ static unsigned int whiteTexture;
|
||||||
static int screenWidth; // Default framebuffer width
|
static int screenWidth; // Default framebuffer width
|
||||||
static int screenHeight; // Default framebuffer height
|
static int screenHeight; // Default framebuffer height
|
||||||
|
|
||||||
// Lighting data
|
|
||||||
static Light lights[MAX_LIGHTS]; // Lights pool
|
|
||||||
static int lightsCount = 0; // Enabled lights counter
|
|
||||||
static int lightsLocs[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light:
|
|
||||||
// enabled, type, position, target, radius, diffuse, intensity, coneAngle
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -382,10 +366,8 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in
|
||||||
static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id
|
static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id
|
||||||
|
|
||||||
static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring)
|
static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring)
|
||||||
static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting)
|
|
||||||
static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
|
static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
|
||||||
static void UnloadDefaultShader(void); // Unload default shader
|
static void UnloadDefaultShader(void); // Unload default shader
|
||||||
static void UnloadStandardShader(void); // Unload standard shader
|
|
||||||
|
|
||||||
static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads)
|
static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads)
|
||||||
static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data
|
static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data
|
||||||
|
@ -397,9 +379,6 @@ static void SetStereoConfig(VrDeviceInfo info);
|
||||||
|
|
||||||
// Set internal projection and modelview matrix depending on eyes tracking data
|
// Set internal projection and modelview matrix depending on eyes tracking data
|
||||||
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView);
|
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView);
|
||||||
|
|
||||||
static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS)
|
|
||||||
static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RLGL_OCULUS_SUPPORT)
|
#if defined(RLGL_OCULUS_SUPPORT)
|
||||||
|
@ -1328,20 +1307,12 @@ void rlglClose(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
UnloadDefaultShader();
|
UnloadDefaultShader();
|
||||||
UnloadStandardShader();
|
|
||||||
UnloadDefaultBuffers();
|
UnloadDefaultBuffers();
|
||||||
|
|
||||||
// Delete default white texture
|
// Delete default white texture
|
||||||
glDeleteTextures(1, &whiteTexture);
|
glDeleteTextures(1, &whiteTexture);
|
||||||
TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
|
TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
|
||||||
|
|
||||||
// Unload lights
|
|
||||||
if (lightsCount > 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < lightsCount; i++) free(lights[i]);
|
|
||||||
lightsCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(draws);
|
free(draws);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -2003,8 +1974,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||||
if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array
|
if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array
|
||||||
if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array
|
if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array
|
||||||
|
|
||||||
// TODO: Support OpenGL 1.1 lighting system
|
|
||||||
|
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
rlMultMatrixf(MatrixToFloat(transform));
|
rlMultMatrixf(MatrixToFloat(transform));
|
||||||
rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a);
|
rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a);
|
||||||
|
@ -2070,10 +2039,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||||
// Check if glossiness is located in shader and upload value
|
// Check if glossiness is located in shader and upload value
|
||||||
int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness");
|
int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness");
|
||||||
if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness);
|
if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness);
|
||||||
|
|
||||||
// Set shader lights values for enabled lights
|
|
||||||
// NOTE: Lights array location points are obtained on shader loading (if available)
|
|
||||||
if (lightsCount > 0) SetShaderLightsValues(material.shader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set shader textures (diffuse, normal, specular)
|
// Set shader textures (diffuse, normal, specular)
|
||||||
|
@ -2528,25 +2493,6 @@ Shader GetDefaultShader(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get default shader
|
|
||||||
// NOTE: Inits global variable standardShader
|
|
||||||
Shader GetStandardShader(void)
|
|
||||||
{
|
|
||||||
Shader shader = { 0 };
|
|
||||||
|
|
||||||
#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
|
// Get shader uniform location
|
||||||
int GetShaderLocation(Shader shader, const char *uniformName)
|
int GetShaderLocation(Shader shader, const char *uniformName)
|
||||||
{
|
{
|
||||||
|
@ -2571,7 +2517,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
|
||||||
else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4
|
else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4
|
||||||
else TraceLog(WARNING, "Shader value float array size not supported");
|
else TraceLog(WARNING, "Shader value float array size not supported");
|
||||||
|
|
||||||
glUseProgram(0);
|
//glUseProgram(0); // Avoid reseting current shader program, in case other uniforms are set
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2587,7 +2533,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size)
|
||||||
else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4
|
else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4
|
||||||
else TraceLog(WARNING, "Shader value int array size not supported");
|
else TraceLog(WARNING, "Shader value int array size not supported");
|
||||||
|
|
||||||
glUseProgram(0);
|
//glUseProgram(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2599,7 +2545,7 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat)
|
||||||
|
|
||||||
glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat));
|
glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat));
|
||||||
|
|
||||||
glUseProgram(0);
|
//glUseProgram(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2645,73 +2591,6 @@ void EndBlendMode(void)
|
||||||
BeginBlendMode(BLEND_ALPHA);
|
BeginBlendMode(BLEND_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new light, initialize it and add to pool
|
|
||||||
Light CreateLight(int type, Vector3 position, Color diffuse)
|
|
||||||
{
|
|
||||||
Light light = NULL;
|
|
||||||
|
|
||||||
if (lightsCount < MAX_LIGHTS)
|
|
||||||
{
|
|
||||||
// Allocate dynamic memory
|
|
||||||
light = (Light)malloc(sizeof(LightData));
|
|
||||||
|
|
||||||
// Initialize light values with generic values
|
|
||||||
light->id = lightsCount;
|
|
||||||
light->type = type;
|
|
||||||
light->enabled = true;
|
|
||||||
|
|
||||||
light->position = position;
|
|
||||||
light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
|
||||||
light->intensity = 1.0f;
|
|
||||||
light->diffuse = diffuse;
|
|
||||||
|
|
||||||
// Add new light to the array
|
|
||||||
lights[lightsCount] = light;
|
|
||||||
|
|
||||||
// Increase enabled lights count
|
|
||||||
lightsCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS);
|
|
||||||
|
|
||||||
// NOTE: Returning latest created light to avoid crashes
|
|
||||||
light = lights[lightsCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
|
||||||
TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return light;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy a light and take it out of the list
|
|
||||||
void DestroyLight(Light light)
|
|
||||||
{
|
|
||||||
if (light != NULL)
|
|
||||||
{
|
|
||||||
int lightId = light->id;
|
|
||||||
|
|
||||||
// Free dynamic memory allocation
|
|
||||||
free(lights[lightId]);
|
|
||||||
|
|
||||||
// Remove *obj from the pointers array
|
|
||||||
for (int i = lightId; i < lightsCount; i++)
|
|
||||||
{
|
|
||||||
// Resort all the following pointers of the array
|
|
||||||
if ((i + 1) < lightsCount)
|
|
||||||
{
|
|
||||||
lights[i] = lights[i + 1];
|
|
||||||
lights[i]->id = lights[i + 1]->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrease enabled physic objects count
|
|
||||||
lightsCount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init VR device (or simulator)
|
// Init VR device (or simulator)
|
||||||
// NOTE: If device is not available, it fallbacks to default device (simulator)
|
// NOTE: If device is not available, it fallbacks to default device (simulator)
|
||||||
// NOTE: It modifies the global variable: VrDeviceInfo hmd
|
// NOTE: It modifies the global variable: VrDeviceInfo hmd
|
||||||
|
@ -3209,39 +3088,6 @@ static Shader LoadDefaultShader(void)
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
static Shader LoadStandardShader(void)
|
|
||||||
{
|
|
||||||
Shader shader;
|
|
||||||
|
|
||||||
#if !defined(RLGL_NO_STANDARD_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
|
|
||||||
{
|
|
||||||
TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded, using default shader", shader.id);
|
|
||||||
shader = GetDefaultShader();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
shader = GetDefaultShader();
|
|
||||||
TraceLog(WARNING, "[SHDR ID %i] Standard shader not available, using default shader", shader.id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get location handlers to for shader attributes and uniforms
|
// Get location handlers to for shader attributes and uniforms
|
||||||
// NOTE: If any location is not found, loc point becomes -1
|
// NOTE: If any location is not found, loc point becomes -1
|
||||||
static void LoadDefaultShaderLocations(Shader *shader)
|
static void LoadDefaultShaderLocations(Shader *shader)
|
||||||
|
@ -3275,9 +3121,6 @@ static void LoadDefaultShaderLocations(Shader *shader)
|
||||||
shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2");
|
shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2");
|
||||||
|
|
||||||
// TODO: Try to find all expected/recognized shader locations (predefined names, must be documented)
|
// TODO: Try to find all expected/recognized shader locations (predefined names, must be documented)
|
||||||
|
|
||||||
// Try to get lights location points (if available)
|
|
||||||
GetShaderLightsLocations(*shader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload default shader
|
// Unload default shader
|
||||||
|
@ -3292,20 +3135,6 @@ static void UnloadDefaultShader(void)
|
||||||
glDeleteProgram(defaultShader.id);
|
glDeleteProgram(defaultShader.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload standard shader
|
|
||||||
static void UnloadStandardShader(void)
|
|
||||||
{
|
|
||||||
glUseProgram(0);
|
|
||||||
#if !defined(RLGL_NO_STANDARD_SHADER)
|
|
||||||
//glDetachShader(defaultShader, vertexShader);
|
|
||||||
//glDetachShader(defaultShader, fragmentShader);
|
|
||||||
//glDeleteShader(vertexShader); // Already deleted on shader compilation
|
|
||||||
//glDeleteShader(fragmentShader); // Already deleted on shader compilation
|
|
||||||
glDeleteProgram(standardShader.id);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Load default internal buffers (lines, triangles, quads)
|
// Load default internal buffers (lines, triangles, quads)
|
||||||
static void LoadDefaultBuffers(void)
|
static void LoadDefaultBuffers(void)
|
||||||
{
|
{
|
||||||
|
@ -3763,104 +3592,6 @@ static void UnloadDefaultBuffers(void)
|
||||||
free(quads.indices);
|
free(quads.indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get shader locations for lights (up to MAX_LIGHTS)
|
|
||||||
static void GetShaderLightsLocations(Shader shader)
|
|
||||||
{
|
|
||||||
char locName[32] = "lights[x].\0";
|
|
||||||
char locNameUpdated[64];
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
|
||||||
{
|
|
||||||
locName[7] = '0' + i;
|
|
||||||
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "enabled\0");
|
|
||||||
lightsLocs[i][0] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "type\0");
|
|
||||||
lightsLocs[i][1] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "position\0");
|
|
||||||
lightsLocs[i][2] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "direction\0");
|
|
||||||
lightsLocs[i][3] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "radius\0");
|
|
||||||
lightsLocs[i][4] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "diffuse\0");
|
|
||||||
lightsLocs[i][5] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "intensity\0");
|
|
||||||
lightsLocs[i][6] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
|
|
||||||
locNameUpdated[0] = '\0';
|
|
||||||
strcpy(locNameUpdated, locName);
|
|
||||||
strcat(locNameUpdated, "coneAngle\0");
|
|
||||||
lightsLocs[i][7] = glGetUniformLocation(shader.id, locNameUpdated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set shader uniform values for lights
|
|
||||||
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0
|
|
||||||
static void SetShaderLightsValues(Shader shader)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
|
||||||
{
|
|
||||||
if (i < lightsCount)
|
|
||||||
{
|
|
||||||
glUniform1i(lightsLocs[i][0], lights[i]->enabled);
|
|
||||||
|
|
||||||
glUniform1i(lightsLocs[i][1], lights[i]->type);
|
|
||||||
glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255);
|
|
||||||
glUniform1f(lightsLocs[i][6], lights[i]->intensity);
|
|
||||||
|
|
||||||
switch (lights[i]->type)
|
|
||||||
{
|
|
||||||
case LIGHT_POINT:
|
|
||||||
{
|
|
||||||
glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
|
|
||||||
glUniform1f(lightsLocs[i][4], lights[i]->radius);
|
|
||||||
} break;
|
|
||||||
case LIGHT_DIRECTIONAL:
|
|
||||||
{
|
|
||||||
Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position);
|
|
||||||
VectorNormalize(&direction);
|
|
||||||
glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
|
|
||||||
} break;
|
|
||||||
case LIGHT_SPOT:
|
|
||||||
{
|
|
||||||
glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
|
|
||||||
|
|
||||||
Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position);
|
|
||||||
VectorNormalize(&direction);
|
|
||||||
glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
|
|
||||||
|
|
||||||
glUniform1f(lightsLocs[i][7], lights[i]->coneAngle);
|
|
||||||
} break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glUniform1i(lightsLocs[i][0], 0); // Light disabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure stereo rendering (including distortion shader) with HMD device parameters
|
// Configure stereo rendering (including distortion shader) with HMD device parameters
|
||||||
static void SetStereoConfig(VrDeviceInfo hmd)
|
static void SetStereoConfig(VrDeviceInfo hmd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
|
|
||||||
// Vertex shader definition to embed, no external file required
|
|
||||||
static const 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
|
|
||||||
static const 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 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(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);\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(abs(dot(n, h)), 3.0 + 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(float(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(abs(dot(n, h)), 3.0 + 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.0));\n"
|
|
||||||
" vec3 lightToSurface = normalize(surfacePos - l.position);\n"
|
|
||||||
" vec3 lightDir = normalize(-l.direction);\n"
|
|
||||||
" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n"
|
|
||||||
" float attenuation = clamp(float(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(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
|
|
||||||
" }\n"
|
|
||||||
" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" mat3 normalMatrix = mat3(modelMatrix);\n"
|
|
||||||
" vec3 normal = normalize(normalMatrix*fragNormal);\n"
|
|
||||||
" vec3 n = normalize(normal);\n"
|
|
||||||
" vec3 v = normalize(viewDir);\n"
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
|
||||||
" vec4 texelColor = texture2D(texture0, fragTexCoord);\n"
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
" vec4 texelColor = texture(texture0, fragTexCoord);\n"
|
|
||||||
#endif
|
|
||||||
" vec3 lighting = colAmbient.rgb;\n"
|
|
||||||
" if (useNormal == 1)\n"
|
|
||||||
" {\n"
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
|
||||||
" n *= texture2D(texture1, fragTexCoord).rgb;\n"
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
" n *= texture(texture1, fragTexCoord).rgb;\n"
|
|
||||||
#endif
|
|
||||||
" n = normalize(n);\n"
|
|
||||||
" }\n"
|
|
||||||
" float spec = 1.0;\n"
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
|
||||||
" if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;\n"
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
" if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;\n"
|
|
||||||
#endif
|
|
||||||
" for (int i = 0; i < maxLights; i++)\n"
|
|
||||||
" {\n"
|
|
||||||
" if (lights[i].enabled == 1)\n"
|
|
||||||
" {\n"
|
|
||||||
" if(lights[i].type == 0) lighting += CalcPointLight(lights[i], n, v, spec);\n"
|
|
||||||
" else if(lights[i].type == 1) lighting += CalcDirectionalLight(lights[i], n, v, spec);\n"
|
|
||||||
" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
|
||||||
" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
|
|
||||||
#endif
|
|
||||||
"}\n";
|
|
Loading…
Add table
Add a link
Reference in a new issue