From 76c6f0b1e695b4090fd1e98d7f2d7ff7dea25641 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 18:55:26 +0200 Subject: [PATCH] Working on PBR system Moved PBR material loading to example, right decision? --- examples/models/models_material_pbr.c | 185 ++++++++++----------- examples/models/resources/shaders/pbr.fs | 3 +- examples/models/rlights.h | 177 ++++++++++++++++++++ src/models.c | 103 +++--------- src/raylib.h | 14 +- src/rlgl.c | 201 ++++++++++------------- 6 files changed, 390 insertions(+), 293 deletions(-) create mode 100644 examples/models/rlights.h diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 5761b2af7..49a905a87 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -12,32 +12,16 @@ #include "raylib.h" #include "raymath.h" -#define MAX_LIGHTS 4 // Max lights supported by shader -#define LIGHT_DISTANCE 3.5f // Light distance from world center -#define LIGHT_HEIGHT 1.0f // Light height position +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" -typedef enum { - LIGHT_DIRECTIONAL, - LIGHT_POINT -} LightType; +#define CUBEMAP_SIZE 512 // Cubemap texture size +#define IRRADIANCE_SIZE 32 // Irradiance texture size +#define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size +#define BRDF_SIZE 512 // BRDF LUT texture size -typedef struct { - bool enabled; - LightType type; - Vector3 position; - Vector3 target; - Color color; - int enabledLoc; - int typeLoc; - int posLoc; - int targetLoc; - int colorLoc; -} Light; - -int lightsCount = 0; // Current amount of created lights - -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader -void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values +// PBR material loading +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); int main() { @@ -54,33 +38,15 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); - - Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - - SetMaterialTexture(&model.material, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&model.material, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&model.material, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&model.material, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&model.material, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); - - // Set textures filtering for better quality - SetTextureFilter(model.material.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_NORMAL].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_METALNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); - - int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); - SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); + model.material = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode - // Define lights attributes Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader), CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader) }; + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -127,59 +93,88 @@ int main() return 0; } -// Defines a light and get locations from PBR shader -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) +// NOTE: PBR shader is loaded inside this function +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { - Light light = { 0 }; + Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } + + #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader + #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader + + mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); + + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); - if (lightsCount < MAX_LIGHTS) - { - light.enabled = true; - light.type = type; - light.position = pos; - light.target = targ; - light.color = color; + // Set view matrix location + mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); + mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); + + // Set PBR standard maps + SetMaterialTexture(&mat, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&mat, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&mat, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&mat, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&mat, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + + // Set environment maps + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - char enabledName[32] = "lights[x].enabled\0"; - char typeName[32] = "lights[x].type\0"; - char posName[32] = "lights[x].position\0"; - char targetName[32] = "lights[x].target\0"; - char colorName[32] = "lights[x].color\0"; - enabledName[7] = '0' + lightsCount; - typeName[7] = '0' + lightsCount; - posName[7] = '0' + lightsCount; - targetName[7] = '0' + lightsCount; - colorName[7] = '0' + lightsCount; + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); + SetMaterialTexture(&mat, MAP_IRRADIANCE, GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE)); + SetMaterialTexture(&mat, MAP_PREFILTER, GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE)); + SetMaterialTexture(&mat, MAP_BRDF, GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE)); + UnloadTexture(cubemap); + UnloadTexture(texHDR); + + UnloadShader(shdrCubemap); + UnloadShader(shdrIrradiance); + UnloadShader(shdrPrefilter); + UnloadShader(shdrBRDF); + + // Set textures filtering for better quality + SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); + + int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); + SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); - light.enabledLoc = GetShaderLocation(shader, enabledName); - light.typeLoc = GetShaderLocation(shader, typeName); - light.posLoc = GetShaderLocation(shader, posName); - light.targetLoc = GetShaderLocation(shader, targetName); - light.colorLoc = GetShaderLocation(shader, colorName); + // Set up material properties color + mat.maps[MAP_ALBEDO].color = albedo; + mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[MAP_METALNESS].value = metalness; + mat.maps[MAP_ROUGHNESS].value = roughness; + mat.maps[MAP_OCCLUSION].value = 1.0f; + mat.maps[MAP_EMISSION].value = 0.5f; + mat.maps[MAP_HEIGHT].value = 0.5f; - UpdateLightValues(shader, light); - lightsCount++; - } - - return light; -} - -// Send to PBR shader light values -void UpdateLightValues(Shader shader, Light light) -{ - // Send to shader light enabled state and type - SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); - SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); - - // Send to shader light position values - float position[3] = { light.position.x, light.position.y, light.position.z }; - SetShaderValue(shader, light.posLoc, position, 3); - - // Send to shader light target position values - float target[3] = { light.target.x, light.target.y, light.target.z }; - SetShaderValue(shader, light.targetLoc, target, 3); - - // Send to shader light color values - float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; - SetShaderValue(shader, light.colorLoc, diff, 4); + return mat; } diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/pbr.fs index 068148236..38d56c5d7 100644 --- a/examples/models/resources/shaders/pbr.fs +++ b/examples/models/resources/shaders/pbr.fs @@ -8,10 +8,11 @@ #version 330 -#define MAX_LIGHTS 4 #define MAX_REFLECTION_LOD 4.0 #define MAX_DEPTH_LAYER 20 #define MIN_DEPTH_LAYER 10 + +#define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 #define LIGHT_POINT 1 diff --git a/examples/models/rlights.h b/examples/models/rlights.h new file mode 100644 index 000000000..0da3e2cba --- /dev/null +++ b/examples/models/rlights.h @@ -0,0 +1,177 @@ +/********************************************************************************************** +* +* raylib.lights - Some useful functions to deal with lights data +* +* CONFIGURATION: +* +* #define RLIGHTS_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2017 Victor Fisac and Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RLIGHTS_H +#define RLIGHTS_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 4 // Max lights supported by shader +#define LIGHT_DISTANCE 3.5f // Light distance from world center +#define LIGHT_HEIGHT 1.0f // Light height position + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +typedef struct { + bool enabled; + LightType type; + Vector3 position; + Vector3 target; + Color color; + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +int lightsCount = 0; // Current amount of created lights + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values + +#ifdef __cplusplus +} +#endif + +#endif // RLIGHTS_H + + +/*********************************************************************************** +* +* RLIGHTS IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLIGHTS_IMPLEMENTATION) + +#include "raylib.h" + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Defines a light and get locations from PBR shader +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = pos; + light.target = targ; + light.color = color; + + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + lightsCount++; + } + + return light; +} + +// Send to PBR shader light values +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); + SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, 3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, 3); + + // Send to shader light color values + float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, diff, 4); +} + +#endif // RLIGHTS_IMPLEMENTATION \ No newline at end of file diff --git a/src/models.c b/src/models.c index 660ecc793..34156b61e 100644 --- a/src/models.c +++ b/src/models.c @@ -1272,6 +1272,9 @@ Material LoadMaterial(const char *fileName) TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif + // Our material uses the default shader (DIFFUSE, SPECULAR, NORMAL) + material.shader = GetShaderDefault(); + return material; } @@ -1282,8 +1285,8 @@ Material LoadMaterialDefault(void) material.shader = GetShaderDefault(); material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel) - //material.maps[MAP_NORMAL].tex; // NOTE: By default, not set - //material.maps[MAP_SPECULAR].tex; // NOTE: By default, not set + //material.maps[MAP_NORMAL].texture; // NOTE: By default, not set + //material.maps[MAP_SPECULAR].texture; // NOTE: By default, not set material.maps[MAP_DIFFUSE].color = WHITE; // Diffuse color material.maps[MAP_SPECULAR].color = WHITE; // Specular color @@ -1291,58 +1294,6 @@ Material LoadMaterialDefault(void) return material; } -// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) -Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) -{ - Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } - - #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader - #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader - - mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); - - // Get required locations points for PBR material - // NOTE: Those location names must be available and used in the shader code - mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); - mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); - mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); - mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); - mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); - mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); - mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); - - // Set view matrix location - mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); - mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); - mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); - - // Set up material properties color - mat.maps[MAP_ALBEDO].color = albedo; - mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; - mat.maps[MAP_METALNESS].value = metalness; - mat.maps[MAP_ROUGHNESS].value = roughness; - mat.maps[MAP_OCCLUSION].value = 1.0f; - mat.maps[MAP_EMISSION].value = 0.0f; - mat.maps[MAP_HEIGHT].value = 0.0f; - - #define CUBEMAP_SIZE 512 // Cubemap texture size - #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size - #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size - #define BRDF_SIZE 512 // BRDF LUT texture map size - - // Set up environment materials cubemap - Texture2D cubemap = GenTextureCubemap(hdr, CUBEMAP_SIZE); - mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(cubemap, PREFILTERED_SIZE); - mat.maps[MAP_BRDF].texture = GenTextureBRDF(cubemap, BRDF_SIZE); - UnloadTexture(cubemap); - - return mat; -} - // Unload material from memory void UnloadMaterial(Material material) { @@ -1358,96 +1309,96 @@ void UnloadMaterial(Material material) } // Set material texture -void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) +void SetMaterialTexture(Material *mat, int mapType, Texture2D texture) { - mat->maps[texmapType].texture = texture; + mat->maps[mapType].texture = texture; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; } } // Unset texture from material and unload it from GPU -void UnsetMaterialTexture(Material *mat, int texmapType) +void UnsetMaterialTexture(Material *mat, int mapType) { - UnloadTexture(mat->maps[texmapType].texture); - mat->maps[texmapType].texture = (Texture2D){ 0 }; + UnloadTexture(mat->maps[mapType].texture); + mat->maps[mapType].texture = (Texture2D){ 0 }; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; } } @@ -2188,7 +2139,7 @@ static Material LoadMTL(const char *fileName) { #define MAX_BUFFER_SIZE 128 - Material material = { 0 }; // LoadDefaultMaterial(); + Material material = { 0 }; char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; diff --git a/src/raylib.h b/src/raylib.h index 8d93a2144..22ef06cb3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -996,10 +996,9 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Material loading/unloading functions RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) -RLAPI Material LoadMaterialPBR(Texture2D cubemap, Color albedo, float metalness, float roughness); // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS...) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) -RLAPI void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture); // Set material texture -RLAPI void UnsetMaterialTexture(Material *mat, int texmapType); // Unset texture from material and unload it from GPU +RLAPI void SetMaterialTexture(Material *mat, int mapType, Texture2D texture); // Set material texture +RLAPI void UnsetMaterialTexture(Material *mat, int mapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -1048,10 +1047,11 @@ RLAPI void SetMatrixProjection(Matrix proj); // Set RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) // Texture maps generation (PBR) -RLAPI Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture -RLAPI Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture using cubemap data -RLAPI Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture using cubemap data -RLAPI Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture using cubemap data +// NOTE: Required shaders should be provided +RLAPI Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +RLAPI Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +RLAPI Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +RLAPI Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data // Shading begin/end functions RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing diff --git a/src/rlgl.c b/src/rlgl.c index b9576b9bd..e6d1bbfb6 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1957,15 +1957,14 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // Bind shader program glUseProgram(material.shader.id); - // Matrices and other values required by shader //----------------------------------------------------- - // Calculate and send to shader model matrix (used by PBR shader) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, + if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, (float)material.maps[MAP_DIFFUSE].color.g/255, (float)material.maps[MAP_DIFFUSE].color.b/255, (float)material.maps[MAP_DIFFUSE].color.a/255); @@ -1976,6 +1975,9 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) (float)material.maps[MAP_SPECULAR].color.g/255, (float)material.maps[MAP_SPECULAR].color.b/255, (float)material.maps[MAP_SPECULAR].color.a/255); + + if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview); + if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -2417,7 +2419,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get the location of the named uniform GLuint location = glGetUniformLocation(shader.id, name); - TraceLog(LOG_INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); } #endif @@ -2529,18 +2531,13 @@ void SetMatrixModelview(Matrix view) } // Generate cubemap texture from HDR texture -Texture2D GenTextureCubemap(Texture2D skyHDR, int size) +Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - - Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - // Get cubemap shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 @@ -2586,7 +2583,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skyHDR.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2594,7 +2591,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2607,8 +2604,6 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); //glEnable(GL_CULL_FACE); - UnloadShader(shader); - cubemap.width = size; cubemap.height = size; @@ -2616,18 +2611,13 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) } // Generate irradiance texture using cubemap data -Texture2D GenTextureIrradiance(Texture2D cubemap, int size) +Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - // Get irradiance shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "environmentMap"); // Set up shaders constant values @@ -2669,7 +2659,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2677,7 +2667,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2688,9 +2678,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + irradiance.width = size; irradiance.height = size; @@ -2698,18 +2686,13 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) } // Generate prefilter texture using cubemap data -Texture2D GenTexturePrefilter(Texture2D cubemap, int size) +Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - // Get prefilter shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int roughnessLoc = GetShaderLocation(shader, "roughness"); int texmapLoc = GetShaderLocation(shader, "environmentMap"); @@ -2754,7 +2737,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -2775,7 +2758,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; ++i) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2787,9 +2770,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + prefilter.width = size; prefilter.height = size; @@ -2797,15 +2778,10 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) } // Generate BRDF texture using cubemap data -Texture2D GenTextureBRDF(Texture2D cubemap, int size) +Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) { Texture2D brdf = { 0 }; - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - // Generate BRDF convolution texture glGenTextures(1, &brdf.id); glBindTexture(GL_TEXTURE_2D, brdf.id); @@ -2835,8 +2811,6 @@ Texture2D GenTextureBRDF(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - UnloadShader(shader); - brdf.width = size; brdf.height = size; @@ -3380,6 +3354,8 @@ static void SetShaderDefaultLocations(Shader *shader) // Get handles to GLSL uniform locations (vertex shader) shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_PROJECTION] = glGetUniformLocation(shader->id, "projection"); + shader->locs[LOC_MATRIX_VIEW] = glGetUniformLocation(shader->id, "view"); // Get handles to GLSL uniform locations (fragment shader) shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); @@ -3894,9 +3870,9 @@ static void GenDrawQuad(void) // Link vertex attributes glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Draw quad glBindVertexArray(quadVAO); @@ -3908,79 +3884,76 @@ static void GenDrawQuad(void) } // Renders a 1x1 3D cube in NDC -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; static void GenDrawCube(void) { - // Lazy initialization - if (cubeVAO == 0) - { - GLfloat vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; + unsigned int cubeVAO = 0; + unsigned int cubeVBO = 0; - // Set up cube VAO - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); + float vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); // Draw cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - //glDeleteBuffers(1, &cubeVBO); - //glDeleteVertexArrays(1, &cubeVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteVertexArrays(1, &cubeVAO); } #if defined(SUPPORT_VR_SIMULATOR)