public unsafe static Texture2D GetMaterialTexture(ref Model model, int materialIndex, MaterialMapType mapIndex) { Material * materials = (Material *)model.materials.ToPointer(); MaterialMap *maps = (MaterialMap *)materials[0].maps.ToPointer(); return(maps[(int)mapIndex].texture); }
public unsafe static void SetMaterialTexture(ref Model model, int materialIndex, MaterialMapType mapIndex, ref Texture2D texture) { Material * materials = (Material *)model.materials.ToPointer(); MaterialMap *maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)mapIndex].texture = texture; }
public unsafe static int Main() { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib - simple shader mask"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3(0.0f, 1.0f, 2.0f); camera.target = new Vector3(0.0f, 0.0f, 0.0f); camera.up = new Vector3(0.0f, 1.0f, 0.0f); camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; // Define our three models to show the shader on Mesh torus = GenMeshTorus(.3f, 1, 16, 32); Model model1 = LoadModelFromMesh(torus); Mesh cube = GenMeshCube(.8f, .8f, .8f); Model model2 = LoadModelFromMesh(cube); // Generate model to be shaded just to see the gaps in the other two Mesh sphere = GenMeshSphere(1, 16, 16); Model model3 = LoadModelFromMesh(sphere); // Load the shader Shader shader = LoadShader("resources/shaders/glsl330/mask.vs", "resources/shaders/glsl330/mask.fs"); // Load and apply the diffuse texture (colour map) Texture2D texDiffuse = LoadTexture("resources/plasma.png"); Material * materials = (Material *)model1.materials.ToPointer(); MaterialMap *maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)MAP_ALBEDO].texture = texDiffuse; materials = (Material *)model2.materials.ToPointer(); maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)MAP_ALBEDO].texture = texDiffuse; // Using MAP_EMISSION as a spare slot to use for 2nd texture // NOTE: Don't use MAP_IRRADIANCE, MAP_PREFILTER or MAP_CUBEMAP // as they are bound as cube maps Texture2D texMask = LoadTexture("resources/mask.png"); materials = (Material *)model1.materials.ToPointer(); maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)MAP_EMISSION].texture = texMask; materials = (Material *)model2.materials.ToPointer(); maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)MAP_EMISSION].texture = texMask; int *locs = (int *)shader.locs.ToPointer(); locs[(int)LOC_MAP_EMISSION] = GetShaderLocation(shader, "mask"); // Frame is incremented each frame to animate the shader int shaderFrame = GetShaderLocation(shader, "framesCounter"); // Apply the shader to the two models materials = (Material *)model1.materials.ToPointer(); materials[0].shader = shader; materials = (Material *)model2.materials.ToPointer(); materials[0].shader = shader; int framesCounter = 0; Vector3 rotation = new Vector3(0, 0, 0); // Model rotation angles SetTargetFPS(60); // Set to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- framesCounter++; rotation.X += 0.01f; rotation.Y += 0.005f; rotation.Z -= 0.0025f; // Send frames counter to shader for animation // SetShaderValue(shader, shaderFrame, IntPtr.Zero, UNIFORM_INT); // Rotate one of the models model1.transform = MatrixRotateXYZ(rotation); UpdateCamera(ref camera); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(DARKBLUE); BeginMode3D(camera); DrawModel(model1, new Vector3(0.5f, 0, 0), 1, WHITE); DrawModelEx(model2, new Vector3(-.5f, 0, 0), new Vector3(1, 1, 0), 50, new Vector3(1, 1, 1), WHITE); DrawModel(model3, new Vector3(0, 0, -1.5f), 1, WHITE); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawRectangle(16, 698, MeasureText(string.Format("Frame: {0}", framesCounter), 20) + 8, 42, BLUE); DrawText(string.Format("Frame: {0}", framesCounter), 20, 700, 20, WHITE); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model1); UnloadModel(model2); UnloadModel(model3); UnloadTexture(texDiffuse); // Unload default diffuse texture UnloadTexture(texMask); // Unload texture mask UnloadShader(shader); // Unload shader CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return(0); }
public unsafe static int Main() { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; SetConfigFlags(ConfigFlag.FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3(4.0f, 4.0f, 4.0f); camera.target = new Vector3(0.0f, 0.5f, 0.0f); camera.up = new Vector3(0.0f, 1.0f, 0.0f); camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); // Unsafe pointers into model arrays. Material *materials = (Material *)model.materials.ToPointer(); Mesh * meshes = (Mesh *)model.meshes.ToPointer(); // Mesh tangents are generated... and uploaded to GPU // NOTE: New VBO for tangents is generated at default location and also binded to mesh VAO MeshTangents(ref meshes[0]); UnloadMaterial(materials[0]); // get rid of default material materials[0] = LoadMaterialPBR(new Color(255, 255, 255, 255), 1.0f, 1.0f); // Define lights attributes // NOTE: Shader is passed to every light on creation to define shader bindings internally CreateLight(LightType.LIGHT_POINT, new Vector3(LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f), new Vector3(0.0f, 0.0f, 0.0f), new Color(255, 0, 0, 255), materials[0].shader); CreateLight(LightType.LIGHT_POINT, new Vector3(0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE), new Vector3(0.0f, 0.0f, 0.0f), new Color(0, 255, 0, 255), materials[0].shader); CreateLight(LightType.LIGHT_POINT, new Vector3(-LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f), new Vector3(0.0f, 0.0f, 0.0f), new Color(0, 0, 255, 255), materials[0].shader); CreateLight(LightType.LIGHT_DIRECTIONAL, new Vector3(0.0f, LIGHT_HEIGHT * 2.0f, -LIGHT_DISTANCE), new Vector3(0.0f, 0.0f, 0.0f), new Color(255, 0, 255, 255), materials[0].shader); SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode 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(ref camera); // Update camera // Send to material PBR shader camera view position float[] cameraPos = { camera.position.X, camera.position.Y, camera.position.Z }; int * locs = (int *)materials[0].shader.locs.ToPointer(); Utils.SetShaderValue(materials[0].shader, (int)ShaderLocationIndex.LOC_VECTOR_VIEW, cameraPos, ShaderUniformDataType.UNIFORM_VEC3); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Shaders and textures must be unloaded by user, // they could be in use by other models MaterialMap *maps = (MaterialMap *)materials[0].maps.ToPointer(); UnloadTexture(maps[(int)MaterialMapType.MAP_ALBEDO].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_NORMAL].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_METALNESS].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_ROUGHNESS].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_OCCLUSION].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_IRRADIANCE].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_PREFILTER].texture); UnloadTexture(maps[(int)MaterialMapType.MAP_BRDF].texture); UnloadShader(materials[0].shader); UnloadModel(model); // Unload skybox model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return(0); }
// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) // NOTE: PBR shader is loaded inside this function unsafe public static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { Material mat = Raylib.LoadMaterialDefault(); // NOTE: All maps textures are set to { 0 ) string PATH_PBR_VS = "resources/shaders/glsl330/pbr.vs"; string PATH_PBR_FS = "resources/shaders/glsl330/pbr.fs"; mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); // Temporary unsafe pointers into material arrays. MaterialMap *maps = (MaterialMap *)mat.maps.ToPointer(); int * locs = (int *)mat.shader.locs.ToPointer(); // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code locs[(int)ShaderLocationIndex.LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); locs[(int)ShaderLocationIndex.LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); locs[(int)ShaderLocationIndex.LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); locs[(int)ShaderLocationIndex.LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); locs[(int)ShaderLocationIndex.LOC_MAP_OCCLUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); locs[(int)ShaderLocationIndex.LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); locs[(int)ShaderLocationIndex.LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); locs[(int)ShaderLocationIndex.LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); // Set view matrix location locs[(int)ShaderLocationIndex.LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "matModel"); locs[(int)ShaderLocationIndex.LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set PBR standard maps maps[(int)MaterialMapType.MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png"); maps[(int)MaterialMapType.MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png"); maps[(int)MaterialMapType.MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png"); maps[(int)MaterialMapType.MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png"); maps[(int)MaterialMapType.MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); // Set environment maps const string PATH_CUBEMAP_VS = "resources/shaders/glsl330/cubemap.vs"; // Path to equirectangular to cubemap vertex shader const string PATH_CUBEMAP_FS = "resources/shaders/glsl330/cubemap.fs"; // Path to equirectangular to cubemap fragment shader const string PATH_SKYBOX_VS = "resources/shaders/glsl330/skybox.vs"; // Path to skybox vertex shader const string PATH_IRRADIANCE_FS = "resources/shaders/glsl330/irradiance.fs"; // Path to irradiance (GI) calculation fragment shader const string PATH_PREFILTER_FS = "resources/shaders/glsl330/prefilter.fs"; // Path to reflection prefilter calculation fragment shader const string PATH_BRDF_VS = "resources/shaders/glsl330/brdf.vs"; // Path to bidirectional reflectance distribution function vertex shader const string PATH_BRDF_FS = "resources/shaders/glsl330/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); // Setup required shader locations Utils.SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), 0); Utils.SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), 0); Utils.SetShaderValue(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), 0); Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); maps[(int)MaterialMapType.MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); maps[(int)MaterialMapType.MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); maps[(int)MaterialMapType.MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, BRDF_SIZE); UnloadTexture(cubemap); UnloadTexture(texHDR); // Unload already used shaders (to create specific textures) UnloadShader(shdrCubemap); UnloadShader(shdrIrradiance); UnloadShader(shdrPrefilter); UnloadShader(shdrBRDF); // Set textures filtering for better quality SetTextureFilter(maps[(int)MaterialMapType.MAP_ALBEDO].texture, FILTER_BILINEAR); SetTextureFilter(maps[(int)MaterialMapType.MAP_NORMAL].texture, FILTER_BILINEAR); SetTextureFilter(maps[(int)MaterialMapType.MAP_METALNESS].texture, FILTER_BILINEAR); SetTextureFilter(maps[(int)MaterialMapType.MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(maps[(int)MaterialMapType.MAP_OCCLUSION].texture, FILTER_BILINEAR); // Enable sample usage in shader for assigned textures Utils.SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), 1); Utils.SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), 1); Utils.SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), 1); Utils.SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), 1); Utils.SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), 1); int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); Utils.SetShaderValue(mat.shader, renderModeLoc, 0); // Set up material properties color maps[(int)MaterialMapType.MAP_ALBEDO].color = albedo; maps[(int)MaterialMapType.MAP_NORMAL].color = new Color(128, 128, 255, 255); maps[(int)MaterialMapType.MAP_METALNESS].value = metalness; maps[(int)MaterialMapType.MAP_ROUGHNESS].value = roughness; maps[(int)MaterialMapType.MAP_OCCLUSION].value = 1.0f; maps[(int)MaterialMapType.MAP_EMISSION].value = 0.5f; maps[(int)MaterialMapType.MAP_HEIGHT].value = 0.5f; return(mat); }
public unsafe static int Main() { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - plane rotations (yaw, pitch, roll)"); Texture2D texAngleGauge = LoadTexture("resources/angle_gauge.png"); Texture2D texBackground = LoadTexture("resources/background.png"); Texture2D texPitch = LoadTexture("resources/pitch.png"); Texture2D texPlane = LoadTexture("resources/plane.png"); RenderTexture2D framebuffer = LoadRenderTexture(192, 192); // Model loading Model model = LoadModel("resources/plane.obj"); // Load OBJ model // Set map diffuse texture Material * materials = (Material *)model.materials.ToPointer(); MaterialMap *maps = (MaterialMap *)materials[0].maps.ToPointer(); maps[(int)MAP_ALBEDO].texture = LoadTexture("resources/plane_diffuse.png"); GenTextureMipmaps(ref maps[(int)MAP_ALBEDO].texture); Camera3D camera = new Camera3D(); camera.position = new Vector3(0.0f, 60.0f, -120.0f); // Camera3D position perspective camera.target = new Vector3(0.0f, 12.0f, 0.0f); // Camera3D looking at point camera.up = new Vector3(0.0f, 1.0f, 0.0f); // Camera3D up vector (rotation towards target) camera.fovy = 30.0f; // Camera3D field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera3D type float pitch = 0.0f; float roll = 0.0f; float yaw = 0.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Plane roll (x-axis) controls if (IsKeyDown(KEY_LEFT)) { roll += 1.0f; } else if (IsKeyDown(KEY_RIGHT)) { roll -= 1.0f; } else { if (roll > 0.0f) { roll -= 0.5f; } else if (roll < 0.0f) { roll += 0.5f; } } // Plane yaw (y-axis) controls if (IsKeyDown(KEY_S)) { yaw += 1.0f; } else if (IsKeyDown(KEY_A)) { yaw -= 1.0f; } else { if (yaw > 0.0f) { yaw -= 0.5f; } else if (yaw < 0.0f) { yaw += 0.5f; } } // Plane pitch (z-axis) controls if (IsKeyDown(KEY_DOWN)) { pitch += 0.6f; } else if (IsKeyDown(KEY_UP)) { pitch -= 0.6f; } else { if (pitch > 0.3f) { pitch -= 0.3f; } else if (pitch < -0.3f) { pitch += 0.3f; } } // Wraps the phase of an angle to fit between -180 and +180 degrees int pitchOffset = (int)pitch; while (pitchOffset > 180) { pitchOffset -= 360; } while (pitchOffset < -180) { pitchOffset += 360; } pitchOffset *= 10; Matrix4x4 transform = MatrixIdentity(); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD * roll)); transform = MatrixMultiply(transform, MatrixRotateX(DEG2RAD * pitch)); transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD * yaw)); model.transform = transform; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // Draw framebuffer texture (Ahrs Display) int centerX = framebuffer.texture.width / 2; int centerY = framebuffer.texture.height / 2; float scaleFactor = 0.5f; BeginTextureMode(framebuffer); BeginBlendMode((int)BLEND_ALPHA); DrawTexturePro(texBackground, new Rectangle(0, 0, texBackground.width, texBackground.height), new Rectangle(centerX, centerY, texBackground.width * scaleFactor, texBackground.height * scaleFactor), new Vector2(texBackground.width / 2 * scaleFactor, texBackground.height / 2 * scaleFactor + pitchOffset * scaleFactor), roll, WHITE); DrawTexturePro(texPitch, new Rectangle(0, 0, texPitch.width, texPitch.height), new Rectangle(centerX, centerY, texPitch.width * scaleFactor, texPitch.height * scaleFactor), new Vector2(texPitch.width / 2 * scaleFactor, texPitch.height / 2 * scaleFactor + pitchOffset * scaleFactor), roll, WHITE); DrawTexturePro(texPlane, new Rectangle(0, 0, texPlane.width, texPlane.height), new Rectangle(centerX, centerY, texPlane.width * scaleFactor, texPlane.height * scaleFactor), new Vector2(texPlane.width / 2 * scaleFactor, texPlane.height / 2 * scaleFactor), 0, WHITE); EndBlendMode(); EndTextureMode(); // Draw 3D model (recomended to draw 3D always before 2D) BeginMode3D(camera); DrawModel(model, new Vector3(0, 6.0f, 0), 1.0f, WHITE); // Draw 3d model with texture DrawGrid(10, 10.0f); EndMode3D(); // Draw 2D GUI stuff DrawAngleGauge(texAngleGauge, 80, 70, roll, "roll", RED); DrawAngleGauge(texAngleGauge, 190, 70, pitch, "pitch", GREEN); DrawAngleGauge(texAngleGauge, 300, 70, yaw, "yaw", SKYBLUE); DrawRectangle(30, 360, 260, 70, ColorAlpha(SKYBLUE, 0.5f)); DrawRectangleLines(30, 360, 260, 70, ColorAlpha(DARKBLUE, 0.5f)); DrawText("Pitch controlled with: KEY_UP / KEY_DOWN", 40, 370, 10, DARKGRAY); DrawText("Roll controlled with: KEY_LEFT / KEY_RIGHT", 40, 390, 10, DARKGRAY); DrawText("Yaw controlled with: KEY_A / KEY_S", 40, 410, 10, DARKGRAY); // Draw framebuffer texture DrawTextureRec(framebuffer.texture, new Rectangle(0, 0, framebuffer.texture.width, -framebuffer.texture.height), new Vector2(screenWidth - framebuffer.texture.width - 20, 20), ColorAlpha(WHITE, 0.8f)); DrawRectangleLines(screenWidth - framebuffer.texture.width - 20, 20, framebuffer.texture.width, framebuffer.texture.height, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload all loaded data UnloadModel(model); UnloadRenderTexture(framebuffer); UnloadTexture(texAngleGauge); UnloadTexture(texBackground); UnloadTexture(texPitch); UnloadTexture(texPlane); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return(0); }