From 28679e3c7986484228b606b6a96e89c6705f1969 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 14 Jul 2017 01:16:22 +0200 Subject: [PATCH] Working on materials PBR... Some issues with the shader (GPU dependant) --- examples/models/models_material_pbr.c | 13 ++-- examples/models/resources/shaders/pbr.fs | 35 +++++++---- src/models.c | 32 +++++----- src/raylib.h | 58 ++++++++---------- src/rlgl.c | 75 +++++++++++++++++------- 5 files changed, 125 insertions(+), 88 deletions(-) diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index d1b8a1fb2..bb1ecb57e 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -30,11 +30,9 @@ int main() Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - model.material.maps[TEXMAP_ALBEDO].tex = LoadTexture("resources/pbr/trooper_albedo.png"); - - SetShaderValuei(model.material.shader, GetShaderLocation(model.material.shader, "albedo.sampler"), (int[1]){ TEXMAP_ALBEDO }, 1); - SetShaderValuei(model.material.shader, GetShaderLocation(model.material.shader, "albedo.useSampler"), (int[1]){ 1 }, 1); - + //model.material.maps[TEXMAP_ALBEDO].tex = LoadTexture("resources/pbr/trooper_albedo.png"); + SetMaterialTexture(&model.material, TEXMAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); +/* SetMaterialTexture(&model.material, TEXMAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); SetTextureFilter(model.material.maps[TEXMAP_NORMAL].tex, FILTER_BILINEAR); @@ -49,8 +47,9 @@ int main() for (int i = 0; i < 12; i++) { - printf("TexMap %i ID: %i\n", i, model.material.maps[i].tex.id); + //printf("TexMap %i ID: %i\n", i, model.material.maps[i].tex.id); } +*/ SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode @@ -73,7 +72,7 @@ int main() Begin3dMode(camera); - DrawModel(model, VectorZero(), 1.0f, RED); + DrawModel(model, VectorZero(), 1.0f, WHITE); DrawGrid(10, 1.0f); diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/pbr.fs index c22216842..630a9be45 100644 --- a/examples/models/resources/shaders/pbr.fs +++ b/examples/models/resources/shaders/pbr.fs @@ -41,18 +41,23 @@ uniform MaterialProperty albedo; uniform MaterialProperty normals; uniform MaterialProperty metalness; uniform MaterialProperty roughness; -uniform MaterialProperty ao; +uniform MaterialProperty occlusion; uniform MaterialProperty emission; uniform MaterialProperty height; -// Input lighting values -uniform Light lights[MAX_LIGHTS]; - // Input uniform values uniform samplerCube irradianceMap; uniform samplerCube prefilterMap; uniform sampler2D brdfLUT; +//uniform sampler2D albedo; +//uniform sampler2D normals; +//uniform sampler2D metalness; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; + + // Other uniform values uniform int renderMode; uniform vec3 viewPos; @@ -184,17 +189,19 @@ void main() else texCoord = fragTexCoord; // Use default texture coordinates // Fetch material values from texture sampler or color attributes - vec3 color = pow(ComputeMaterialProperty(albedo), vec3(2.2)); - vec3 metal = ComputeMaterialProperty(metalness); - vec3 rough = ComputeMaterialProperty(roughness); - vec3 emiss = ComputeMaterialProperty(emission); - vec3 occlusion = ComputeMaterialProperty(ao); + vec3 color = pow(texture(albedo.sampler, texCoord).rgb, vec3(2.2));//pow(ComputeMaterialProperty(albedo), vec3(2.2)); + vec3 metal = texture(metalness.sampler, texCoord).rgb; //ComputeMaterialProperty(metalness); + vec3 rough = texture(roughness.sampler, texCoord).rgb; //ComputeMaterialProperty(roughness); + vec3 emiss = texture(emission.sampler, texCoord).rgb; //ComputeMaterialProperty(emission); + vec3 ao = texture(occlusion.sampler, texCoord).rgb; //ComputeMaterialProperty(occlusion); + vec3 all = color + metal + rough + emiss + ao; + // Check if normal mapping is enabled if (normals.useSampler == 1) { // Fetch normal map color and transform lighting values to tangent space - normal = ComputeMaterialProperty(normals); + normal = texture(normals.sampler, texCoord).rgb; //ComputeMaterialProperty(normals); normal = normalize(normal*2.0 - 1.0); normal = normalize(normal*TBN); @@ -210,6 +217,7 @@ void main() vec3 Lo = vec3(0.0); vec3 lightDot = vec3(0.0); + /* for (int i = 0; i < MAX_LIGHTS; i++) { if (lights[i].enabled == 1) @@ -251,6 +259,7 @@ void main() lightDot += radiance*NdotL + brdf*lights[i].color.a; } } + */ // Calculate ambient lighting using IBL vec3 F = fresnelSchlickRoughness(max(dot(normal, view), 0.0), F0, rough.r); @@ -268,7 +277,7 @@ void main() vec3 reflection = prefilterColor*(F*brdf.x + brdf.y); // Calculate final lighting - vec3 ambient = (kD*diffuse + reflection)*occlusion; + vec3 ambient = (kD*diffuse + reflection)*ao; // Calculate fragment color based on render mode vec3 fragmentColor = ambient + Lo + emiss; // Physically Based Rendering @@ -277,7 +286,7 @@ void main() else if (renderMode == 2) fragmentColor = normal; // Normals else if (renderMode == 3) fragmentColor = metal; // Metalness else if (renderMode == 4) fragmentColor = rough; // Roughness - else if (renderMode == 5) fragmentColor = occlusion; // Ambient Occlusion + else if (renderMode == 5) fragmentColor = ao; // Ambient Occlusion else if (renderMode == 6) fragmentColor = emiss; // Emission else if (renderMode == 7) fragmentColor = lightDot; // Lighting else if (renderMode == 8) fragmentColor = kS; // Fresnel @@ -291,5 +300,5 @@ void main() fragmentColor = pow(fragmentColor, vec3(1.0/2.2)); // Calculate final fragment color - finalColor = vec4(fragmentColor, 1.0); + finalColor = vec4(all, 1.0);//vec4(fragmentColor, 1.0); // It works, so texture is correctly binded! } diff --git a/src/models.c b/src/models.c index bd283e8fa..733266d37 100644 --- a/src/models.c +++ b/src/models.c @@ -1305,20 +1305,20 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); - // Set up PBR shader material texture units - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "albedo.sampler"), (int[1]){ TEXMAP_ALBEDO }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "normals.sampler"), (int[1]){ TEXMAP_NORMAL }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "metalness.sampler"), (int[1]){ TEXMAP_METALNESS }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "roughness.sampler"), (int[1]){ TEXMAP_ROUGHNESS }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "occlusion.sampler"), (int[1]){ TEXMAP_OCCLUSION }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "emission.sampler"), (int[1]){ TEXMAP_EMISSION }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "height.sampler"), (int[1]){ TEXMAP_HEIGHT }, 1); - - // Set up environment shader texture units - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "irradianceMap"), (int[1]){ TEXMAP_IRRADIANCE }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "prefilterMap"), (int[1]){ TEXMAP_PREFILTER }, 1); - SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "brdfLUT"), (int[1]){ TEXMAP_BRDF }, 1); - + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_TEXMAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_TEXMAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_TEXMAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_TEXMAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_TEXMAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_TEXMAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_TEXMAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_TEXMAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_TEXMAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_TEXMAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + + // Set view matrix location mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set up material properties color @@ -1337,8 +1337,8 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou // Set up environment materials cubemap Texture2D cubemap = rlGenMapCubemap(hdr, CUBEMAP_SIZE); - mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); + // mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); + // mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); mat.maps[TEXMAP_BRDF].tex = rlGenMapBRDF(cubemap, BRDF_SIZE); UnloadTexture(cubemap); diff --git a/src/raylib.h b/src/raylib.h index 2ee40a695..4115d6366 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -530,53 +530,47 @@ typedef enum { LOC_VERTEX_POSITION = 0, LOC_VERTEX_TEXCOORD01, LOC_VERTEX_TEXCOORD02, - LOC_VERTEX_TEXCOORD03, - LOC_VERTEX_TEXCOORD04, LOC_VERTEX_NORMAL, LOC_VERTEX_TANGENT, LOC_VERTEX_COLOR, LOC_MATRIX_MVP, LOC_MATRIX_VIEW, LOC_MATRIX_PROJECTION, - LOC_TEXTURE_MAP01, - LOC_TEXTURE_MAP02, - LOC_TEXTURE_MAP03, - LOC_TEXTURE_MAP04, - LOC_TEXTURE_MAP05, - LOC_TEXTURE_MAP06, - LOC_TEXTURE_MAP07, - LOC_TEXTURE_MAP08, - LOC_TEXTURE_COLOR01, - LOC_TEXTURE_COLOR02, - LOC_TEXTURE_COLOR03, - LOC_TEXTURE_COLOR04, - LOC_TEXTURE_COLOR05, - LOC_TEXTURE_COLOR06, - LOC_TEXTURE_COLOR07, - LOC_TEXTURE_COLOR08 + LOC_COLOR_DIFFUSE, + LOC_COLOR_SPECULAR, + LOC_COLOR_AMBIENT, + LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE + LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR + LOC_TEXMAP_NORMAL, + LOC_TEXMAP_ROUGHNESS, + LOC_TEXMAP_OCCUSION, + LOC_TEXMAP_EMISSION, + LOC_TEXMAP_HEIGHT, + LOC_TEXMAP_CUBEMAP, + LOC_TEXMAP_IRRADIANCE, + LOC_TEXMAP_PREFILTER, + LOC_TEXMAP_BRDF } ShaderLocationIndex; -typedef enum { - TEXMAP_DIFFUSE = 0, - TEXMAP_SPECULAR = 1, -} TexmapBasicIndex; +#define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO +#define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS typedef enum { - TEXMAP_ALBEDO = 0, - TEXMAP_METALNESS = 1, + TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE + TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR TEXMAP_NORMAL = 2, TEXMAP_ROUGHNESS = 3, TEXMAP_OCCLUSION, TEXMAP_EMISSION, - TEXMAP_HEIGHT -} TexmapPBRIndex; + TEXMAP_HEIGHT, + TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_BRDF +} TexmapIndex; -typedef enum { - TEXMAP_CUBEMAP = 8, - TEXMAP_IRRADIANCE, - TEXMAP_PREFILTER, - TEXMAP_BRDF, -} TexmapEnvIndex; +#define TEXMAP_DIFFUSE TEXMAP_ALBEDO +#define TEXMAP_SPECULAR TEXMAP_METALNESS // Texture formats // NOTE: Support depends on OpenGL version and platform diff --git a/src/rlgl.c b/src/rlgl.c index c2d11b240..3606f774d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -337,7 +337,7 @@ static void LoadTextureCompressed(unsigned char *data, int width, int height, in static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) -static void LoadShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) +static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnLoadShaderDefault(void); // Unload default shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) @@ -2383,7 +2383,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) */ // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_TEXTURE_COLOR01], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, (float)material.maps[TEXMAP_DIFFUSE].color.g/255, (float)material.maps[TEXMAP_DIFFUSE].color.b/255, (float)material.maps[TEXMAP_DIFFUSE].color.a/255); @@ -2396,8 +2396,8 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // (float)material.colAmbient.a/255); // Upload to shader material.colSpecular (if available) - if (material.shader.locs[LOC_TEXTURE_COLOR03] != -1) - glUniform4f(material.shader.locs[LOC_TEXTURE_COLOR03], (float)material.maps[TEXMAP_SPECULAR].color.r/255, + if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[TEXMAP_SPECULAR].color.r/255, (float)material.maps[TEXMAP_SPECULAR].color.g/255, (float)material.maps[TEXMAP_SPECULAR].color.b/255, (float)material.maps[TEXMAP_SPECULAR].color.a/255); @@ -2419,7 +2419,8 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) glActiveTexture(GL_TEXTURE0 + i); if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].tex.id); else glBindTexture(GL_TEXTURE_2D, material.maps[i].tex.id); - glUniform1i(material.shader.locs[LOC_TEXTURE_MAP01 + i], i); + + glUniform1i(material.shader.locs[LOC_TEXMAP_DIFFUSE + i], i); } } @@ -2794,8 +2795,8 @@ Shader LoadShader(char *vsFileName, char *fsFileName) { shader.id = LoadShaderProgram(vShaderStr, fShaderStr); - // After shader loading, we try to load default location names - if (shader.id > 0) LoadShaderDefaultLocations(&shader); + // After shader loading, we TRY to set default location names + if (shader.id > 0) SetShaderDefaultLocations(&shader); // Shader strings must be freed free(vShaderStr); @@ -2807,6 +2808,32 @@ Shader LoadShader(char *vsFileName, char *fsFileName) TraceLog(WARNING, "Custom shader could not be loaded"); shader = defaultShader; } + + + // Get available shader uniforms + // NOTE: This information is useful for debug... + int uniformCount = -1; + + glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount); + + for(int i = 0; i < uniformCount; i++) + { + int namelen = -1; + int num = -1; + char name[256]; // Assume no variable names longer than 256 + GLenum type = GL_ZERO; + + // Get the name of the uniforms + glGetActiveUniform(shader.id, i,sizeof(name) - 1, &namelen, &num, &type, name); + + name[namelen] = 0; + + // Get the location of the named uniform + GLuint location = glGetUniformLocation(shader.id, name); + + TraceLog(INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + } + #endif return shader; @@ -2860,7 +2887,8 @@ int GetShaderLocation(Shader shader, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - if (location == -1) TraceLog(DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); + if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader uniform [%s] COULD NOT BE FOUND", shader.id, uniformName); + else TraceLog(INFO, "[SHDR ID %i] Shader uniform [%s] set at location: %i", shader.id, uniformName, location); #endif return location; } @@ -3019,7 +3047,7 @@ void InitVrSimulator(int vrDevice) #if defined(SUPPORT_DISTORTION_SHADER) // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); - if (vrConfig.distortionShader.id > 0) LoadShaderDefaultLocations(&vrConfig.distortionShader); + if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader); #endif SetStereoConfig(hmd); @@ -3423,7 +3451,17 @@ static Shader LoadShaderDefault(void) if (shader.id > 0) { TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); - LoadShaderDefaultLocations(&shader); + + // Set default shader locations + // Get handles to GLSL input attibute locations + shader.locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader.id, "vertexPosition"); + shader.locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader.id, "vertexTexCoord"); + shader.locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader.id, "vertexColor"); + + // Get handles to GLSL uniform locations + shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); + shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); } else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); @@ -3432,7 +3470,7 @@ static Shader LoadShaderDefault(void) // Get location handlers to for shader attributes and uniforms // NOTE: If any location is not found, loc point becomes -1 -static void LoadShaderDefaultLocations(Shader *shader) +static void SetShaderDefaultLocations(Shader *shader) { // NOTE: Default shader attrib locations have been fixed before linking: // vertex position location = 0 @@ -3454,13 +3492,10 @@ static void LoadShaderDefaultLocations(Shader *shader) shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader->locs[LOC_TEXTURE_COLOR01] = glGetUniformLocation(shader->id, "colDiffuse"); - shader->locs[LOC_TEXTURE_COLOR02] = glGetUniformLocation(shader->id, "colAmbient"); - shader->locs[LOC_TEXTURE_COLOR03] = glGetUniformLocation(shader->id, "colSpecular"); - - shader->locs[LOC_TEXTURE_MAP01] = glGetUniformLocation(shader->id, "texture0"); - shader->locs[LOC_TEXTURE_MAP02] = glGetUniformLocation(shader->id, "texture1"); - shader->locs[LOC_TEXTURE_MAP03] = glGetUniformLocation(shader->id, "texture2"); + shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); + shader->locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); + shader->locs[LOC_TEXMAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); + shader->locs[LOC_TEXMAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } @@ -3746,8 +3781,8 @@ static void DrawDefaultBuffers() Matrix matMVP = MatrixMultiply(modelview, projection); glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); - glUniform4f(currentShader.locs[LOC_TEXTURE_COLOR01], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.locs[LOC_TEXTURE_MAP01], 0); + glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(currentShader.locs[LOC_TEXMAP_DIFFUSE], 0); // NOTE: Additional map textures not considered for default buffers drawing }