Merge pull request #120 from victorfisac/develop

Standard Lighting (2/3)
This commit is contained in:
Ray 2016-05-21 20:11:23 +02:00
commit 9811a37690
11 changed files with 479 additions and 419 deletions

View file

@ -1,85 +0,0 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec3 fragNormal;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 fragTintColor;
// Output fragment color
out vec4 finalColor;
// NOTE: Add here your custom variables
// Light uniform values
uniform vec3 lightAmbientColor = vec3(0.6, 0.3, 0.0);
uniform vec3 lightDiffuseColor = vec3(1.0, 0.5, 0.0);
uniform vec3 lightSpecularColor = vec3(0.0, 1.0, 0.0);
uniform float lightIntensity = 1.0;
uniform float lightSpecIntensity = 1.0;
// Material uniform values
uniform vec3 matAmbientColor = vec3(1.0, 1.0, 1.0);
uniform vec3 matSpecularColor = vec3(1.0, 1.0, 1.0);
uniform float matGlossiness = 50.0;
// World uniform values
uniform vec3 lightPosition;
uniform vec3 cameraPosition;
// Fragment shader output data
out vec4 fragColor;
// Calculate ambient lighting component
vec3 AmbientLighting()
{
return (matAmbientColor*lightAmbientColor);
}
// Calculate diffuse lighting component
vec3 DiffuseLighting(in vec3 N, in vec3 L)
{
// Lambertian reflection calculation
float diffuse = clamp(dot(N, L), 0, 1);
return (fragTintColor.xyz*lightDiffuseColor*lightIntensity*diffuse);
}
// Calculate specular lighting component
vec3 SpecularLighting(in vec3 N, in vec3 L, in vec3 V)
{
float specular = 0.0;
// Calculate specular reflection only if the surface is oriented to the light source
if (dot(N, L) > 0)
{
// Calculate half vector
vec3 H = normalize(L + V);
// Calculate specular intensity
specular = pow(dot(N, H), 3 + matGlossiness);
}
return (matSpecularColor*lightSpecularColor*lightSpecIntensity*specular);
}
void main()
{
// Normalize input vectors
vec3 L = normalize(lightPosition);
vec3 V = normalize(cameraPosition);
vec3 N = normalize(fragNormal);
// Calculate lighting components
vec3 ambient = AmbientLighting();
vec3 diffuse = DiffuseLighting(N, L);
vec3 specular = SpecularLighting(N, L, V);
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord);
// Calculate final fragment color
finalColor = vec4(texelColor.rgb*(ambient + diffuse + specular), texelColor.a);
}

View file

@ -1,29 +0,0 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
// Input uniform values
uniform mat4 mvpMatrix;
// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec3 fragNormal;
// NOTE: Add here your custom variables
uniform mat4 modelMatrix;
void main()
{
// Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord;
// Calculate view vector normal from model
mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
fragNormal = normalize(normalMatrix*vertexNormal);
// Calculate final vertex position
gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,136 @@
#version 330
in vec3 fragPosition;
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragNormal;
out vec4 finalColor;
uniform sampler2D texture0;
uniform vec4 colAmbient;
uniform vec4 colDiffuse;
uniform vec4 colSpecular;
uniform float glossiness;
uniform mat4 modelMatrix;
uniform vec3 viewDir;
struct Light {
int enabled;
int type;
vec3 position;
vec3 direction;
vec4 diffuse;
float intensity;
float attenuation;
float coneAngle;
};
const int maxLights = 8;
uniform int lightsCount;
uniform Light lights[maxLights];
vec3 CalcPointLight(Light l, vec3 n, vec3 v)
{
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
vec3 surfaceToLight = l.position - surfacePos;
// Diffuse shading
float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);
float diff = 1.0/dot(surfaceToLight/l.attenuation, surfaceToLight/l.attenuation)*brightness*l.intensity;
// Specular shading
float spec = 0.0;
if (diff > 0.0)
{
vec3 h = normalize(-l.direction + v);
spec = pow(dot(n, h), 3 + glossiness);
}
return (diff*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb);
}
vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v)
{
vec3 lightDir = normalize(-l.direction);
// Diffuse shading
float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
// Specular shading
float spec = 0.0;
if (diff > 0.0)
{
vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3 + glossiness);
}
// Combine results
return (diff*l.intensity*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb);
}
vec3 CalcSpotLight(Light l, vec3 n, vec3 v)
{
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
vec3 lightToSurface = normalize(surfacePos - l.position);
vec3 lightDir = normalize(-l.direction);
// Diffuse shading
float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
// Spot attenuation
float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);
attenuation = dot(lightToSurface, -lightDir);
float lightToSurfaceAngle = degrees(acos(attenuation));
if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
// Combine diffuse and attenuation
float diffAttenuation = diff*attenuation;
// Specular shading
float spec = 0.0;
if (diffAttenuation > 0.0)
{
vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3 + glossiness);
}
return falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb);
}
void main()
{
// Calculate fragment normal in screen space
mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
vec3 normal = normalize(normalMatrix*fragNormal);
// Normalize normal and view direction vectors
vec3 n = normalize(normal);
vec3 v = normalize(viewDir);
// Calculate diffuse texture color fetching
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 lighting = colAmbient.rgb;
for (int i = 0; i < lightsCount; i++)
{
// Check if light is enabled
if (lights[i].enabled == 1)
{
// Calculate lighting based on light type
switch (lights[i].type)
{
case 0: lighting += CalcPointLight(lights[i], n, v); break;
case 1: lighting += CalcDirectionalLight(lights[i], n, v); break;
case 2: lighting += CalcSpotLight(lights[i], n, v); break;
default: break;
}
}
}
// Calculate final fragment color
finalColor = vec4(texelColor.rgb*lighting, texelColor.a);
}

View file

@ -0,0 +1,23 @@
#version 330
in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 vertexTexCoord;
in vec4 vertexColor;
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragNormal;
uniform mat4 mvpMatrix;
void main()
{
fragPosition = vertexPosition;
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = vertexNormal;
gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
}

View file

@ -1,171 +0,0 @@
/*******************************************************************************************
*
* raylib [shaders] example - Basic lighting: Blinn-Phong
*
* This example has been created using raylib 1.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define SHININESS_SPEED 1.0f
#define LIGHT_SPEED 0.25f
// Light type
typedef struct Light {
Vector3 position;
Vector3 direction;
float intensity;
float specIntensity;
Color diffuse;
Color ambient;
Color specular;
} Light;
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
// Camera initialization
Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
// Model initialization
Vector3 position = { 0.0f, 0.0f, 0.0f };
Model model = LoadModel("resources/model/dwarf.obj");
Shader shader = LoadShader("resources/shaders/glsl330/phong.vs", "resources/shaders/glsl330/phong.fs");
SetModelShader(&model, shader);
// Shader locations initialization
int lIntensityLoc = GetShaderLocation(shader, "lightIntensity");
int lAmbientLoc = GetShaderLocation(shader, "lightAmbientColor");
int lDiffuseLoc = GetShaderLocation(shader, "lightDiffuseColor");
int lSpecularLoc = GetShaderLocation(shader, "lightSpecularColor");
int lSpecIntensityLoc = GetShaderLocation(shader, "lightSpecIntensity");
int mAmbientLoc = GetShaderLocation(shader, "matAmbientColor");
int mSpecularLoc = GetShaderLocation(shader, "matSpecularColor");
int mGlossLoc = GetShaderLocation(shader, "matGlossiness");
// Camera and light vectors shader locations
int cameraLoc = GetShaderLocation(shader, "cameraPosition");
int lightLoc = GetShaderLocation(shader, "lightPosition");
// Model and View matrix locations (required for lighting)
int modelLoc = GetShaderLocation(shader, "modelMatrix");
//int viewLoc = GetShaderLocation(shader, "viewMatrix"); // Not used
// Light and material definitions
Light light;
Material matBlinn;
// Light initialization
light.position = (Vector3){ 4.0f, 2.0f, 0.0f };
light.direction = (Vector3){ 5.0f, 1.0f, 1.0f };
light.intensity = 1.0f;
light.diffuse = WHITE;
light.ambient = (Color){ 150, 75, 0, 255 };
light.specular = WHITE;
light.specIntensity = 1.0f;
// Material initialization
matBlinn.colDiffuse = WHITE;
matBlinn.colAmbient = (Color){ 50, 50, 50, 255 };
matBlinn.colSpecular = WHITE;
matBlinn.glossiness = 50.0f;
// Setup camera
SetCameraMode(CAMERA_FREE); // Set camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera position
// NOTE: Model transform can be set in model.transform or directly with params at draw... WATCH OUT!
SetShaderValueMatrix(shader, modelLoc, model.transform); // Send model matrix to shader
//SetShaderValueMatrix(shader, viewLoc, GetCameraMatrix(camera)); // Not used
// Glossiness input control
if(IsKeyDown(KEY_UP)) matBlinn.glossiness += SHININESS_SPEED;
else if(IsKeyDown(KEY_DOWN))
{
matBlinn.glossiness -= SHININESS_SPEED;
if( matBlinn.glossiness < 0) matBlinn.glossiness = 0.0f;
}
// Light X movement
if (IsKeyDown(KEY_D)) light.position.x += LIGHT_SPEED;
else if(IsKeyDown(KEY_A)) light.position.x -= LIGHT_SPEED;
// Light Y movement
if (IsKeyDown(KEY_LEFT_SHIFT)) light.position.y += LIGHT_SPEED;
else if (IsKeyDown(KEY_LEFT_CONTROL)) light.position.y -= LIGHT_SPEED;
// Light Z movement
if (IsKeyDown(KEY_S)) light.position.z += LIGHT_SPEED;
else if (IsKeyDown(KEY_W)) light.position.z -= LIGHT_SPEED;
// Send light values to shader
SetShaderValue(shader, lIntensityLoc, &light.intensity, 1);
SetShaderValue(shader, lAmbientLoc, ColorToFloat(light.ambient), 3);
SetShaderValue(shader, lDiffuseLoc, ColorToFloat(light.diffuse), 3);
SetShaderValue(shader, lSpecularLoc, ColorToFloat(light.specular), 3);
SetShaderValue(shader, lSpecIntensityLoc, &light.specIntensity, 1);
// Send material values to shader
SetShaderValue(shader, mAmbientLoc, ColorToFloat(matBlinn.colAmbient), 3);
SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.colSpecular), 3);
SetShaderValue(shader, mGlossLoc, &matBlinn.glossiness, 1);
// Send camera and light transform values to shader
SetShaderValue(shader, cameraLoc, VectorToFloat(camera.position), 3);
SetShaderValue(shader, lightLoc, VectorToFloat(light.position), 3);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
Begin3dMode(camera);
DrawModel(model, position, 4.0f, matBlinn.colDiffuse);
DrawSphere(light.position, 0.5f, GOLD);
DrawGrid(20, 1.0f);
End3dMode();
DrawFPS(10, 10); // Draw FPS
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader);
UnloadModel(model);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View file

@ -0,0 +1,118 @@
/*******************************************************************************************
*
* raylib [shaders] example - Standard lighting (materials and lights)
*
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
* 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
*
* This example has been created using raylib 1.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available)
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader");
// Define the camera to look into our 3d world
Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model
Texture2D texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture
Material material = LoadStandardMaterial();
material.texDiffuse = texDiffuse;
material.colDiffuse = (Color){255, 255, 255, 255};
material.colAmbient = (Color){0, 0, 10, 255};
material.colSpecular = (Color){255, 255, 255, 255};
material.glossiness = 50.0f;
dwarf.material = material; // Apply material to model
Light spotLight = CreateLight(LIGHT_SPOT, (Vector3){3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255});
spotLight->target = (Vector3){0.0f, 0.0f, 0.0f};
spotLight->intensity = 2.0f;
spotLight->diffuse = (Color){255, 100, 100, 255};
spotLight->coneAngle = 60.0f;
Light dirLight = CreateLight(LIGHT_DIRECTIONAL, (Vector3){0.0f, -3.0f, -3.0f}, (Color){255, 255, 255, 255});
dirLight->target = (Vector3){1.0f, -2.0f, -2.0f};
dirLight->intensity = 2.0f;
dirLight->diffuse = (Color){100, 255, 100, 255};
Light pointLight = CreateLight(LIGHT_POINT, (Vector3){0.0f, 4.0f, 5.0f}, (Color){255, 255, 255, 255});
pointLight->intensity = 2.0f;
pointLight->diffuse = (Color){100, 100, 255, 255};
pointLight->attenuation = 3.0f;
// Setup orbital camera
SetCameraMode(CAMERA_ORBITAL); // Set a orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
Begin3dMode(camera);
DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture
DrawLights(); // Draw all created lights in 3D world
DrawGrid(10, 1.0f); // Draw a grid
End3dMode();
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadMaterial(material); // Unload material and assigned textures
UnloadModel(dwarf); // Unload model
// Destroy all created lights
DestroyLight(pointLight);
DestroyLight(dirLight);
DestroyLight(spotLight);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View file

@ -384,7 +384,7 @@ RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingP
for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
{ {
if(mixChannelsActive_g[mixIndex] == NULL) break; if(mixChannelsActive_g[mixIndex] == NULL) break;
else if(mixIndex = MAX_MIX_CHANNELS - 1) return -1; // error else if(mixIndex == MAX_MIX_CHANNELS - 1) return -1; // error
} }
if(InitMixChannel(sampleRate, mixIndex, channels, floatingPoint)) if(InitMixChannel(sampleRate, mixIndex, channels, floatingPoint))
@ -772,7 +772,7 @@ int PlayMusicStream(int musicIndex, char *fileName)
for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
{ {
if(mixChannelsActive_g[mixIndex] == NULL) break; if(mixChannelsActive_g[mixIndex] == NULL) break;
else if(mixIndex = MAX_MIX_CHANNELS - 1) return 2; // error else if(mixIndex == MAX_MIX_CHANNELS - 1) return 2; // error
} }
if (strcmp(GetExtension(fileName),"ogg") == 0) if (strcmp(GetExtension(fileName),"ogg") == 0)
@ -956,7 +956,7 @@ float GetMusicTimeLength(int index)
// Get current music time played (in seconds) // Get current music time played (in seconds)
float GetMusicTimePlayed(int index) float GetMusicTimePlayed(int index)
{ {
float secondsPlayed; float secondsPlayed = 0.0f;
if(index < MAX_MUSIC_STREAMS && currentMusic[index].mixc) if(index < MAX_MUSIC_STREAMS && currentMusic[index].mixc)
{ {
if (currentMusic[index].chipTune) if (currentMusic[index].chipTune)
@ -972,7 +972,6 @@ float GetMusicTimePlayed(int index)
secondsPlayed = (float)samplesPlayed / (currentMusic[index].mixc->sampleRate * currentMusic[index].mixc->channels); secondsPlayed = (float)samplesPlayed / (currentMusic[index].mixc->sampleRate * currentMusic[index].mixc->channels);
} }
} }
return secondsPlayed; return secondsPlayed;
} }

View file

@ -65,6 +65,16 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw a line in 3D world space
void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color)
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex3f(startPos.x, startPos.y, startPos.z);
rlVertex3f(endPos.x, endPos.y, endPos.z);
rlEnd();
}
// Draw cube // Draw cube
// NOTE: Cube position is the center position // NOTE: Cube position is the center position
void DrawCube(Vector3 position, float width, float height, float length, Color color) void DrawCube(Vector3 position, float width, float height, float length, Color color)
@ -292,9 +302,9 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for(int i = 0; i < (rings + 2); i++) for (int i = 0; i < (rings + 2); i++)
{ {
for(int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sin(DEG2RAD*(270+(180/(rings + 1))*i)),
@ -331,9 +341,9 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for(int i = 0; i < (rings + 2); i++) for (int i = 0; i < (rings + 2); i++)
{ {
for(int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sin(DEG2RAD*(270+(180/(rings + 1))*i)),
@ -376,7 +386,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
if (radiusTop > 0) if (radiusTop > 0)
{ {
// Draw Body ------------------------------------------------------------------------------------- // Draw Body -------------------------------------------------------------------------------------
for(int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left
rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right
@ -388,7 +398,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
} }
// Draw Cap -------------------------------------------------------------------------------------- // Draw Cap --------------------------------------------------------------------------------------
for(int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, height, 0); rlVertex3f(0, height, 0);
rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop);
@ -398,7 +408,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
else else
{ {
// Draw Cone ------------------------------------------------------------------------------------- // Draw Cone -------------------------------------------------------------------------------------
for(int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, height, 0); rlVertex3f(0, height, 0);
rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
@ -407,7 +417,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
} }
// Draw Base ----------------------------------------------------------------------------------------- // Draw Base -----------------------------------------------------------------------------------------
for(int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, 0, 0); rlVertex3f(0, 0, 0);
rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
@ -421,7 +431,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
// NOTE: It could be also used for pyramid and cone // NOTE: It could be also used for pyramid and cone
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color) void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)
{ {
if(sides < 3) sides = 3; if (sides < 3) sides = 3;
rlPushMatrix(); rlPushMatrix();
rlTranslatef(position.x, position.y, position.z); rlTranslatef(position.x, position.y, position.z);
@ -429,7 +439,7 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for(int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
@ -490,7 +500,7 @@ void DrawGrid(int slices, float spacing)
int halfSlices = slices / 2; int halfSlices = slices / 2;
rlBegin(RL_LINES); rlBegin(RL_LINES);
for(int i = -halfSlices; i <= halfSlices; i++) for (int i = -halfSlices; i <= halfSlices; i++)
{ {
if (i == 0) if (i == 0)
{ {
@ -732,13 +742,13 @@ Material LoadDefaultMaterial(void)
return material; return material;
} }
// Load standard material (uses standard models shader) // Load standard material (uses material attributes and lighting shader)
// NOTE: Standard shader supports multiple maps and lights // NOTE: Standard shader supports multiple maps and lights
Material LoadStandardMaterial(void) Material LoadStandardMaterial(void)
{ {
Material material = LoadDefaultMaterial(); Material material = LoadDefaultMaterial();
//material.shader = GetStandardShader(); material.shader = GetStandardShader();
return material; return material;
} }
@ -788,9 +798,9 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ }; Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ };
for(int z = 0; z < mapZ-1; z++) for (int z = 0; z < mapZ-1; z++)
{ {
for(int x = 0; x < mapX-1; x++) for (int x = 0; x < mapX-1; x++)
{ {
// Fill vertices array with data // Fill vertices array with data
//---------------------------------------------------------- //----------------------------------------------------------
@ -1240,7 +1250,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
//Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates
model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
model.material.colDiffuse = tint; // model.material.colDiffuse = tint;
rlglDrawMesh(model.mesh, model.material, model.transform); rlglDrawMesh(model.mesh, model.material, model.transform);
} }
@ -1407,7 +1417,7 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius
float vector = VectorDotProduct(raySpherePos, ray.direction); float vector = VectorDotProduct(raySpherePos, ray.direction);
float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
if(d >= 0.0f) collision = true; if (d >= 0.0f) collision = true;
return collision; return collision;
} }
@ -1422,14 +1432,14 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi
float vector = VectorDotProduct(raySpherePos, ray.direction); float vector = VectorDotProduct(raySpherePos, ray.direction);
float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
if(d >= 0.0f) collision = true; if (d >= 0.0f) collision = true;
// Calculate collision point // Calculate collision point
Vector3 offset = ray.direction; Vector3 offset = ray.direction;
float collisionDistance = 0; float collisionDistance = 0;
// Check if ray origin is inside the sphere to calculate the correct collision point // Check if ray origin is inside the sphere to calculate the correct collision point
if(distance < sphereRadius) collisionDistance = vector + sqrt(d); if (distance < sphereRadius) collisionDistance = vector + sqrt(d);
else collisionDistance = vector - sqrt(d); else collisionDistance = vector - sqrt(d);
VectorScale(&offset, collisionDistance); VectorScale(&offset, collisionDistance);
@ -1767,11 +1777,11 @@ static Mesh LoadOBJ(const char *fileName)
// First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles
// NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition) // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
// NOTE: faces MUST be defined as TRIANGLES (3 vertex per face) // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face)
while(!feof(objFile)) while (!feof(objFile))
{ {
fscanf(objFile, "%c", &dataType); fscanf(objFile, "%c", &dataType);
switch(dataType) switch (dataType)
{ {
case '#': // Comments case '#': // Comments
case 'o': // Object name (One OBJ file can contain multible named meshes) case 'o': // Object name (One OBJ file can contain multible named meshes)
@ -1832,11 +1842,11 @@ static Mesh LoadOBJ(const char *fileName)
// Second reading pass: Get vertex data to fill intermediate arrays // Second reading pass: Get vertex data to fill intermediate arrays
// NOTE: This second pass is required in case of multiple meshes defined in same OBJ // NOTE: This second pass is required in case of multiple meshes defined in same OBJ
// TODO: Consider that different meshes can have different vertex data available (position, texcoords, normals) // TODO: Consider that different meshes can have different vertex data available (position, texcoords, normals)
while(!feof(objFile)) while (!feof(objFile))
{ {
fscanf(objFile, "%c", &dataType); fscanf(objFile, "%c", &dataType);
switch(dataType) switch (dataType)
{ {
case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break; case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break;
case 'v': case 'v':
@ -1893,11 +1903,11 @@ static Mesh LoadOBJ(const char *fileName)
if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName);
// Third reading pass: Get faces (triangles) data and fill VertexArray // Third reading pass: Get faces (triangles) data and fill VertexArray
while(!feof(objFile)) while (!feof(objFile))
{ {
fscanf(objFile, "%c", &dataType); fscanf(objFile, "%c", &dataType);
switch(dataType) switch (dataType)
{ {
case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break; case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break;
case 'f': case 'f':
@ -2013,7 +2023,7 @@ static Material LoadMTL(const char *fileName)
return material; return material;
} }
while(!feof(mtlFile)) while (!feof(mtlFile))
{ {
fgets(buffer, MAX_BUFFER_SIZE, mtlFile); fgets(buffer, MAX_BUFFER_SIZE, mtlFile);
@ -2071,8 +2081,7 @@ static Material LoadMTL(const char *fileName)
int shininess = 0; int shininess = 0;
sscanf(buffer, "Ns %i", &shininess); sscanf(buffer, "Ns %i", &shininess);
// Normalize shininess value to material glossiness attribute material.glossiness = (float)shininess;
material.glossiness = (float)shininess/1000;
} }
else if (buffer[1] == 'i') // Ni int Refraction index. else if (buffer[1] == 'i') // Ni int Refraction index.
{ {

View file

@ -398,7 +398,7 @@ typedef struct Shader {
// Uniform locations // Uniform locations
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
int tintColorLoc; // Color uniform location point (fragment shader) int tintColorLoc; // Diffuse color uniform location point (fragment shader)
// Texture map locations // Texture map locations
int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader)
@ -418,7 +418,7 @@ typedef struct Material {
Color colAmbient; // Ambient color Color colAmbient; // Ambient color
Color colSpecular; // Specular color Color colSpecular; // Specular color
float glossiness; // Glossiness level float glossiness; // Glossiness level (Ranges from 0 to 1000)
float normalDepth; // Normal map depth float normalDepth; // Normal map depth
} Material; } Material;
@ -430,25 +430,19 @@ typedef struct Model {
} Model; } Model;
// Light type // Light type
// TODO: Review contained data to support different light types and features
typedef struct LightData { typedef struct LightData {
int id; int id;
int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
bool enabled; bool enabled;
Vector3 position; Vector3 position;
Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction) Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
float attenuation; // Lost of light intensity with distance (use radius?) float attenuation; // Lost of light intensity with distance (world distance)
Color diffuse; // Use Vector3 diffuse (including intensities)? Color diffuse; // Use Vector3 diffuse
float intensity; float intensity;
Color specular; float coneAngle; // Spot light max angle
//float specFactor; // Specular intensity ?
//Color ambient; // Required?
float coneAngle; // SpotLight
} LightData, *Light; } LightData, *Light;
// Light types // Light types
@ -808,6 +802,7 @@ const char *SubText(const char *text, int position, int length);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Basic 3d Shapes Drawing Functions (Module: models) // Basic 3d Shapes Drawing Functions (Module: models)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube
void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires
@ -836,6 +831,7 @@ void SetModelTexture(Model *model, Texture2D texture); // Link a textur
Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadMaterial(const char *fileName); // Load material data (from file)
Material LoadDefaultMaterial(void); // Load default material (uses default models shader) Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader)
void UnloadMaterial(Material material); // Unload material textures from VRAM void UnloadMaterial(Material material); // Unload material textures from VRAM
void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
@ -865,6 +861,7 @@ void UnloadShader(Shader shader); // Unload a
void SetDefaultShader(void); // Set default shader to be used in batch draw void SetDefaultShader(void); // Set default shader to be used in batch draw
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
Shader GetDefaultShader(void); // Get default shader Shader GetDefaultShader(void); // Get default shader
Shader GetStandardShader(void); // Get default shader
Texture2D GetDefaultTexture(void); // Get default texture Texture2D GetDefaultTexture(void); // Get default texture
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
@ -875,6 +872,7 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
void DrawLights(void); // Draw all created lights in 3D world
void DestroyLight(Light light); // Destroy a light and take it out of the list void DestroyLight(Light light); // Destroy a light and take it out of the list
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View file

@ -191,6 +191,7 @@ static bool useTempBuffer = false;
// Shader Programs // Shader Programs
static Shader defaultShader; static Shader defaultShader;
static Shader standardShader;
static Shader currentShader; // By default, defaultShader static Shader currentShader; // By default, defaultShader
// Flags for supported extensions // Flags for supported extensions
@ -236,6 +237,7 @@ static Shader LoadDefaultShader(void); // Load default shader (just vertex
static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting) 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
@ -1018,6 +1020,7 @@ void rlglInit(void)
// Init default Shader (customized for GL 3.3 and ES2) // Init default Shader (customized for GL 3.3 and ES2)
defaultShader = LoadDefaultShader(); defaultShader = LoadDefaultShader();
standardShader = LoadStandardShader();
currentShader = defaultShader; currentShader = defaultShader;
LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads) LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads)
@ -1046,6 +1049,7 @@ 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
@ -1393,7 +1397,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
{ {
TraceLog(WARNING, "Framebuffer object could not be created..."); TraceLog(WARNING, "Framebuffer object could not be created...");
switch(status) switch (status)
{ {
case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break; case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
@ -1757,19 +1761,33 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
// Send combined model-view-projection matrix to shader // Send combined model-view-projection matrix to shader
glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
// Setup shader uniforms for material related data
// TODO: Check if using standard shader to get location points
// Upload to shader material.colDiffuse // Upload to shader material.colDiffuse
float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse); glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
// Check if using standard shader to get location points
// NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
if (material.shader.id == standardShader.id)
{
// Send model transformations matrix to shader
glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform));
// Send view transformation matrix to shader. View matrix 8, 9 and 10 are view direction vector axis values (target - position)
glUniform3f(glGetUniformLocation(material.shader.id, "viewDir"), matView.m8, matView.m9, matView.m10);
// Setup shader uniforms for lights
SetShaderLights(material.shader);
// Upload to shader material.colAmbient
glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255);
// Upload to shader material.colSpecular
glUniform4f(glGetUniformLocation(material.shader.id, "colSpecular"), (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255);
// TODO: Upload to shader material.colAmbient // Upload to shader glossiness
// glUniform4f(???, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); glUniform1f(glGetUniformLocation(material.shader.id, "glossiness"), material.glossiness);
}
// TODO: Upload to shader material.colSpecular
// glUniform4f(???, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255);
// Set shader textures (diffuse, normal, specular) // Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -1791,13 +1809,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2
// TODO: Upload to shader glossiness
//glUniform1f(???, material.glossiness);
} }
// Setup shader uniforms for lights
//SetShaderLights(material.shader);
if (vaoSupported) if (vaoSupported)
{ {
@ -2148,6 +2160,17 @@ Shader GetDefaultShader(void)
#endif #endif
} }
// Get default shader
Shader GetStandardShader(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
return standardShader;
#else
Shader shader = { 0 };
return shader;
#endif
}
// Get shader uniform location // Get shader uniform location
int GetShaderLocation(Shader shader, const char *uniformName) int GetShaderLocation(Shader shader, const char *uniformName)
{ {
@ -2225,7 +2248,6 @@ void SetBlendMode(int mode)
} }
// Create a new light, initialize it and add to pool // Create a new light, initialize it and add to pool
// TODO: Review creation parameters (only generic ones)
Light CreateLight(int type, Vector3 position, Color diffuse) Light CreateLight(int type, Vector3 position, Color diffuse)
{ {
// Allocate dynamic memory // Allocate dynamic memory
@ -2237,10 +2259,9 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
light->enabled = true; light->enabled = true;
light->position = position; light->position = position;
light->direction = (Vector3){ 0.0f, 0.0f, 0.0f }; light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
light->intensity = 1.0f; light->intensity = 1.0f;
light->diffuse = diffuse; light->diffuse = diffuse;
light->specular = WHITE;
// Add new light to the array // Add new light to the array
lights[lightsCount] = light; lights[lightsCount] = light;
@ -2251,6 +2272,31 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
return light; return light;
} }
// Draw all created lights in 3D world
void DrawLights(void)
{
for (int i = 0; i < lightsCount; i++)
{
switch (lights[i]->type)
{
case LIGHT_POINT: DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); break;
case LIGHT_DIRECTIONAL:
{
Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
} break;
case LIGHT_SPOT:
{
Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
DrawCylinderWires(lights[i]->position, 0.0f, 0.3f*lights[i]->coneAngle/50, 0.6f, 5, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
} break;
default: break;
}
}
}
// Destroy a light and take it out of the list // Destroy a light and take it out of the list
void DestroyLight(Light light) void DestroyLight(Light light)
{ {
@ -2468,15 +2514,15 @@ static Shader LoadDefaultShader(void)
"varying vec4 fragColor; \n" "varying vec4 fragColor; \n"
#endif #endif
"uniform sampler2D texture0; \n" "uniform sampler2D texture0; \n"
"uniform vec4 fragTintColor; \n" "uniform vec4 colDiffuse; \n"
"void main() \n" "void main() \n"
"{ \n" "{ \n"
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
" vec4 texelColor = texture(texture0, fragTexCoord); \n" " vec4 texelColor = texture(texture0, fragTexCoord); \n"
" finalColor = texelColor*fragTintColor*fragColor; \n" " finalColor = texelColor*colDiffuse*fragColor; \n"
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
" vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0 " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
" gl_FragColor = texelColor*fragTintColor*fragColor; \n" " gl_FragColor = texelColor*colDiffuse*fragColor; \n"
#endif #endif
"} \n"; "} \n";
@ -2493,25 +2539,17 @@ static Shader LoadDefaultShader(void)
// Load standard shader // Load standard shader
// NOTE: This shader supports: // NOTE: This shader supports:
// - Up to 3 different maps: diffuse, normal, specular // - Up to 3 different maps: diffuse, normal, specular
// - Material properties: colDiffuse, colAmbient, colSpecular, glossiness, normalDepth // - Material properties: colAmbient, colDiffuse, colSpecular, glossiness, normalDepth
// - Up to 8 lights: Point, Directional or Spot // - Up to 8 lights: Point, Directional or Spot
static Shader LoadStandardShader(void) static Shader LoadStandardShader(void)
{ {
Shader shader; // Load standard shader (TODO: rewrite as char pointers)
Shader shader = LoadShader("resources/shaders/standard.vs", "resources/shaders/standard.fs");
char *vShaderStr;
char *fShaderStr;
// TODO: Implement standard uber-shader, supporting all features (GLSL 100 / GLSL 330)
// NOTE: Shader could be quite extensive so it could be implemented in external files (standard.vs/standard.fs)
shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id); if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id); else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id);
if (shader.id != 0) LoadDefaultShaderLocations(&shader); // TODO: Review locations fetching if (shader.id != 0) LoadDefaultShaderLocations(&shader);
return shader; return shader;
} }
@ -2540,7 +2578,7 @@ static void LoadDefaultShaderLocations(Shader *shader)
shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix");
// Get handles to GLSL uniform locations (fragment shader) // Get handles to GLSL uniform locations (fragment shader)
shader->tintColorLoc = glGetUniformLocation(shader->id, "fragTintColor"); shader->tintColorLoc = glGetUniformLocation(shader->id, "colDiffuse");
shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0"); shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0");
shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1"); shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1");
shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2"); shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2");
@ -2554,10 +2592,23 @@ static void UnloadDefaultShader(void)
//glDetachShader(defaultShader, vertexShader); //glDetachShader(defaultShader, vertexShader);
//glDetachShader(defaultShader, fragmentShader); //glDetachShader(defaultShader, fragmentShader);
//glDeleteShader(vertexShader); // Already deleted on shader compilation //glDeleteShader(vertexShader); // Already deleted on shader compilation
//glDeleteShader(fragmentShader); // Already deleted on sahder compilation //glDeleteShader(fragmentShader); // Already deleted on shader compilation
glDeleteProgram(defaultShader.id); glDeleteProgram(defaultShader.id);
} }
// Unload standard shader
static void UnloadStandardShader(void)
{
glUseProgram(0);
//glDetachShader(defaultShader, vertexShader);
//glDetachShader(defaultShader, fragmentShader);
//glDeleteShader(vertexShader); // Already deleted on shader compilation
//glDeleteShader(fragmentShader); // Already deleted on shader compilation
glDeleteProgram(standardShader.id);
}
// Load default internal buffers (lines, triangles, quads) // Load default internal buffers (lines, triangles, quads)
static void LoadDefaultBuffers(void) static void LoadDefaultBuffers(void)
{ {
@ -3003,58 +3054,75 @@ static void UnloadDefaultBuffers(void)
// Sets shader uniform values for lights array // Sets shader uniform values for lights array
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f
// TODO: Review memcpy() and parameters pass
static void SetShaderLights(Shader shader) static void SetShaderLights(Shader shader)
{ {
/* int locPoint = glGetUniformLocation(shader.id, "lightsCount");
// NOTE: Standard Shader must include the following data:
// Shader Light struct
struct Light {
vec3 position;
vec3 direction;
vec3 diffuse;
float intensity;
}
const int maxLights = 8;
uniform int lightsCount; // Number of lights
uniform Light lights[maxLights];
*/
int locPoint;
char locName[32] = "lights[x].position\0";
glUseProgram(shader.id);
locPoint = glGetUniformLocation(shader.id, "lightsCount");
glUniform1i(locPoint, lightsCount); glUniform1i(locPoint, lightsCount);
char locName[32] = "lights[x].position\0";
for (int i = 0; i < lightsCount; i++) for (int i = 0; i < lightsCount; i++)
{ {
locName[7] = '0' + i; locName[7] = '0' + i;
memcpy(&locName[10], "position\0", strlen("position\0")); memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1);
locPoint = glGetUniformLocation(shader.id, locName); locPoint = GetShaderLocation(shader, locName);
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); glUniform1i(locPoint, lights[i]->enabled);
memcpy(&locName[10], "direction\0", strlen("direction\0")); memcpy(&locName[10], "type\0", strlen("type\0") + 1);
locPoint = glGetUniformLocation(shader.id, locName); locPoint = GetShaderLocation(shader, locName);
glUniform3f(locPoint, lights[i]->direction.x, lights[i]->direction.y, lights[i]->direction.z); glUniform1i(locPoint, lights[i]->type);
memcpy(&locName[10], "diffuse\0", strlen("diffuse\0")); memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2);
locPoint = glGetUniformLocation(shader.id, locName); locPoint = glGetUniformLocation(shader.id, locName);
glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255 ); glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255);
memcpy(&locName[10], "intensity\0", strlen("intensity\0")); memcpy(&locName[10], "intensity\0", strlen("intensity\0"));
locPoint = glGetUniformLocation(shader.id, locName); locPoint = glGetUniformLocation(shader.id, locName);
glUniform1f(locPoint, lights[i]->intensity); glUniform1f(locPoint, lights[i]->intensity);
switch (lights[i]->type)
{
case LIGHT_POINT:
{
memcpy(&locName[10], "position\0", strlen("position\0") + 1);
locPoint = GetShaderLocation(shader, locName);
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
memcpy(&locName[10], "attenuation\0", strlen("attenuation\0"));
locPoint = GetShaderLocation(shader, locName);
glUniform1f(locPoint, lights[i]->attenuation);
} break;
case LIGHT_DIRECTIONAL:
{
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
locPoint = GetShaderLocation(shader, locName);
Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
VectorNormalize(&direction);
glUniform3f(locPoint, direction.x, direction.y, direction.z);
} break;
case LIGHT_SPOT:
{
memcpy(&locName[10], "position\0", strlen("position\0") + 1);
locPoint = GetShaderLocation(shader, locName);
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
locPoint = GetShaderLocation(shader, locName);
Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
VectorNormalize(&direction);
glUniform3f(locPoint, direction.x, direction.y, direction.z);
memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
locPoint = GetShaderLocation(shader, locName);
glUniform1f(locPoint, lights[i]->coneAngle);
} break;
default: break;
}
// TODO: Pass to the shader any other required data from LightData struct // TODO: Pass to the shader any other required data from LightData struct
} }
glUseProgram(0);
} }
// Read text data from file // Read text data from file
@ -3227,7 +3295,7 @@ static void TraceLog(int msgType, const char *text, ...)
va_list args; va_list args;
va_start(args, text); va_start(args, text);
switch(msgType) switch (msgType)
{ {
case INFO: fprintf(stdout, "INFO: "); break; case INFO: fprintf(stdout, "INFO: "); break;
case ERROR: fprintf(stdout, "ERROR: "); break; case ERROR: fprintf(stdout, "ERROR: "); break;

View file

@ -196,40 +196,34 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
// Material type // Material type
typedef struct Material { typedef struct Material {
Shader shader; Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular)
Texture2D texDiffuse; // Diffuse texture Texture2D texDiffuse; // Diffuse texture
Texture2D texNormal; // Normal texture Texture2D texNormal; // Normal texture
Texture2D texSpecular; // Specular texture Texture2D texSpecular; // Specular texture
Color colDiffuse; Color colDiffuse; // Diffuse color
Color colAmbient; Color colAmbient; // Ambient color
Color colSpecular; Color colSpecular; // Specular color
float glossiness; float glossiness; // Glossiness level (Ranges from 0 to 1000)
float normalDepth; float normalDepth; // Normal map depth
} Material; } Material;
// Light type // Light type
// TODO: Review contained data to support different light types and features
typedef struct LightData { typedef struct LightData {
int id; int id;
int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
bool enabled; bool enabled;
Vector3 position; Vector3 position;
Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction) Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
float attenuation; // Lost of light intensity with distance (use radius?) float attenuation; // Lost of light intensity with distance (world distance)
Color diffuse; // Use Vector3 diffuse (including intensities)? Color diffuse; // Use Vector3 diffuse
float intensity; float intensity;
Color specular; float coneAngle; // Spot light max angle
//float specFactor; // Specular intensity ?
//Color ambient; // Required?
float coneAngle; // SpotLight
} LightData, *Light; } LightData, *Light;
// Color blending modes (pre-defined) // Color blending modes (pre-defined)