Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.8k
raylib generic uber shader and custom shaders
Dealing with custom shaders and making them generic is not an easy task. There are many things to consider for a shader because, after all, shaders are responsible for processing all the data sent to the GPU (mesh, materials, textures, lighting) to generate the final frame.
Finding a unified generic shader to deal with all kinds of stuff is very complicated so, after analyzing some of the big engines out there, I decided to go for a custom uber-shader-based solution.
By default, raylib's shader struct is defined as:
typedefstructShader {unsignedintid;// Shader program idint*locs;// Shader locations array (MAX_SHADER_LOCATIONS)}Shader;
This struct provides an array to store shader locations, those locations can be accessed by position using predefined enum values for convenience:
// Shader location point typetypedefenum {SHADER_LOC_VERTEX_POSITION=0,SHADER_LOC_VERTEX_TEXCOORD01,SHADER_LOC_VERTEX_TEXCOORD02,SHADER_LOC_VERTEX_NORMAL,SHADER_LOC_VERTEX_TANGENT,SHADER_LOC_VERTEX_COLOR,SHADER_LOC_MATRIX_MVP,SHADER_LOC_MATRIX_MODEL,SHADER_LOC_MATRIX_VIEW,SHADER_LOC_MATRIX_PROJECTION,SHADER_LOC_VECTOR_VIEW,SHADER_LOC_COLOR_DIFFUSE,SHADER_LOC_COLOR_SPECULAR,SHADER_LOC_COLOR_AMBIENT,SHADER_LOC_MAP_ALBEDO,// SHADER_LOC_MAP_DIFFUSESHADER_LOC_MAP_METALNESS,// SHADER_LOC_MAP_SPECULARSHADER_LOC_MAP_NORMAL,SHADER_LOC_MAP_ROUGHNESS,SHADER_LOC_MAP_OCCUSION,SHADER_LOC_MAP_EMISSION,SHADER_LOC_MAP_HEIGHT,SHADER_LOC_MAP_CUBEMAP,SHADER_LOC_MAP_IRRADIANCE,SHADER_LOC_MAP_PREFILTER,SHADER_LOC_MAP_BRDF}ShaderLocationIndex;#defineSHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO#defineSHADER_LOC_MAP_SPECULAR SHADER_LOC_MAP_METALNESS
When loading a shader, raylib tries to find some default attributes and uniforms locations:
#defineRL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0#defineRL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Binded by default to shader location: 1#defineRL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Binded by default to shader location: 2#defineRL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Binded by default to shader location: 3#defineRL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Binded by default to shader location: 4#defineRL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5#defineRL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix#defineRL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix#defineRL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix#defineRL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix#defineRL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))#defineRL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)#defineRL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)#defineRL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)#defineRL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
The uniform locations belong to VertexShader or FragmentShader:
uniformmat4 mvp;// VS: ModelViewProjection matrixuniformmat4 matView;// VS: View matrixuniformmat4 matProjection;// VS: Projection matrixuniformmat4 matModel;// VS: Model matrixuniformmat4 matNormal;// VS: Normal matrixuniformvec4 colDiffuse;// FS: Diffuse coloruniformsampler2D texture0;// FS: GL_TEXTURE0uniformsampler2D texture1;// FS: GL_TEXTURE1uniformsampler2D texture2;// FS: GL_TEXTURE2
Those are the attributes/uniform names used by the internaldefault shader. It's recommended to use that naming convention on custom shaders as well to make sure everything will be automatically set up onLoadShader(). However, some of the default attribute names could be re-defined inconfig.h in case it was necessary.
Shaders are also directly related to the Material struct:
// Material type (generic)typedefstructMaterial {Shadershader;// Material shaderMaterialMap*maps;// Material maps array (MAX_MATERIAL_MAPS)float*params;// Material generic parameters (if required)}Material;
By default,Material supports a number of maps (texture and properties) that can be accessed for convenience using the provided values:
// Material map typetypedefenum {MATERIAL_MAP_ALBEDO=0,// MATERIAL_MAP_DIFFUSEMATERIAL_MAP_METALNESS=1,// MATERIAL_MAP_SPECULARMATERIAL_MAP_NORMAL=2,MATERIAL_MAP_ROUGHNESS=3,MATERIAL_MAP_OCCLUSION,MATERIAL_MAP_EMISSION,MATERIAL_MAP_HEIGHT,MATERIAL_MAP_CUBEMAP,// NOTE: Uses GL_TEXTURE_CUBE_MAPMATERIAL_MAP_IRRADIANCE,// NOTE: Uses GL_TEXTURE_CUBE_MAPMATERIAL_MAP_PREFILTER,// NOTE: Uses GL_TEXTURE_CUBE_MAPMATERIAL_MAP_BRDF}TexmapIndex;#defineMATERIAL_MAP_DIFFUSE MATERIAL_MAP_ALBEDO#defineMATERIAL_MAP_SPECULAR MATERIAL_MAP_METALNESS
When drawing, maps may be internally bound depending on the availability:
// Default material loading exampleMaterialmaterial=LoadMaterialDefault();// Default shader assigned to materialmaterial.maps[MATERIAL_MAP_DIFFUSE].texture=LoadTexture("tex_diffuse.png");// texture unit 0 activated (available in material shader)material.maps[MATERIAL_MAP_SPECULAR].texture=LoadTexture("tex_specular.png");// texture unit 1 activated (available in material shader)
User can load any custom shader using providedMaterial andShader structs:
Materialmaterial= {0 };// Empty materialmaterial.shader=LoadShader("custom_shader.vs","custom_shader.fs");// Set up location points in case names are not predefined ones or more locations are required// Use: GetShaderLocation() and SetShaderValue*() functionsmaterial.maps[0].texture=LoadTexture("tex_albedo.png");material.maps[1].texture=LoadTexture("tex_metalness.png");material.maps[2].texture=LoadTexture("tex_normal.png");
www.raylib.com | itch.io | GitHub | Discord | YouTube
- Architecture
- Syntax analysis
- Data structures
- Enumerated types
- External dependencies
- GLFW dependency
- libc dependency
- Platforms and graphics
- Input system
- Default shader
- Custom shaders
- Coding conventions
- Integration with other libs
- Working on Windows
- Working on macOS
- Working on GNU Linux
- Working on Chrome OS
- Working on FreeBSD
- Working on Raspberry Pi
- Working for Android
- Working for Web (HTML5)
- Working on exaequOS Web Computer
- Creating Discord Activities
- Working anywhere with CMake
- CMake Build Options
- raylib templates: Get started easily
- How To: Quick C/C++ Setup in Visual Studio 2022, GCC or MinGW
- How To: C# Visual Studio Setup
- How To: VSCode
- How To: Eclipse
- How To: Sublime Text
- How To: Code::Blocks