diff options
| author | chriscamacho <[email protected]> | 2020-03-24 13:27:14 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-03-24 14:27:14 +0100 |
| commit | efe359d61303b2148199c009abab34e44b0ab04f (patch) | |
| tree | 9d0b1e0ed67617f65cc5ce99db178c9232bfe5f4 | |
| parent | c45fe62abcf7d710678f7f4bc25dc9b1bfdc8ea2 (diff) | |
| download | raylib-efe359d61303b2148199c009abab34e44b0ab04f.tar.gz raylib-efe359d61303b2148199c009abab34e44b0ab04f.zip | |
as per request spotlight example (#1146)
Co-authored-by: codifies <[email protected]>
| -rw-r--r-- | examples/Makefile | 3 | ||||
| -rw-r--r-- | examples/shaders/resources/raysan.png | bin | 0 -> 15064 bytes | |||
| -rw-r--r-- | examples/shaders/resources/shaders/glsl100/spotlight.fs | 52 | ||||
| -rw-r--r-- | examples/shaders/resources/shaders/glsl330/spotlight.fs | 53 | ||||
| -rw-r--r-- | examples/shaders/shaders_spotlight.c | 225 |
5 files changed, 332 insertions, 1 deletions
diff --git a/examples/Makefile b/examples/Makefile index 3ae76baf..ecd4344a 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -456,7 +456,8 @@ SHADERS = \ shaders/shaders_eratosthenes \ shaders/shaders_basic_lighting \ shaders/shaders_fog \ - shaders/shaders_simple_mask + shaders/shaders_simple_mask \ + shaders/shaders_spotlight AUDIO = \ audio/audio_module_playing \ diff --git a/examples/shaders/resources/raysan.png b/examples/shaders/resources/raysan.png Binary files differnew file mode 100644 index 00000000..3d4e70fe --- /dev/null +++ b/examples/shaders/resources/raysan.png diff --git a/examples/shaders/resources/shaders/glsl100/spotlight.fs b/examples/shaders/resources/shaders/glsl100/spotlight.fs new file mode 100644 index 00000000..204b89a7 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/spotlight.fs @@ -0,0 +1,52 @@ +#version 100 + +precision mediump float; + +#define MAX_SPOTS 4 +#define RADIUS 256.0 +#define INNER 200.0 + +// Inputs +// array of spotlight positions +uniform vec2 spots[MAX_SPOTS]; + +uniform float screenWidth; // width of the screen + +void main() +{ + + float alpha; + // get the position of the current fragment (screen coordinates!) + vec2 pos = vec2(gl_FragCoord.x, gl_FragCoord.y); + + + // find out which spotlight is nearest + float d = 65000.0; // some high value + float di = 0.0; + + for (int i = 0; i < MAX_SPOTS; i++) + { + di = distance(pos, spots[i]); + if (d > di) d = di; + } + + // d now equals distance to nearest spot... + if (d > RADIUS) { + alpha = 1.0; + } else { + if (d < INNER) { + alpha = 0.0; + } else { + alpha = (d - INNER) / (RADIUS - INNER); + } + } + + // right hand side of screen is dimly lit, could make the + // threshold value user definable. + if (pos.x > screenWidth/2.0 && alpha > 0.9) { + alpha = 0.9; + } + + // could make the black out colour user definable... + gl_FragColor = vec4( 0, 0, 0, alpha); +} diff --git a/examples/shaders/resources/shaders/glsl330/spotlight.fs b/examples/shaders/resources/shaders/glsl330/spotlight.fs new file mode 100644 index 00000000..f97722c6 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/spotlight.fs @@ -0,0 +1,53 @@ +#version 330 + +// Output fragment color +out vec4 finalColor; + +#define MAX_SPOTS 4 +#define RADIUS 256 +#define INNER 200 + +// Inputs +// array of spotlight positions +uniform vec2 spots[MAX_SPOTS]; + +uniform float screenWidth; // width of the screen + +void main() +{ + + float alpha; + // get the position of the current fragment (screen coordinates!) + vec2 pos = vec2(gl_FragCoord.x, gl_FragCoord.y); + + + // find out which spotlight is nearest + float d = 65000; // some high value + float di = 0; + + for (int i = 0; i < MAX_SPOTS; i++) + { + di = distance(pos, spots[i]); + if (d > di) d = di; + } + + // d now equals distance to nearest spot... + if (d > RADIUS) { + alpha = 1.0; + } else { + if (d < INNER) { + alpha = 0.0; + } else { + alpha = (d - INNER) / (RADIUS - INNER); + } + } + + // right hand side of screen is dimly lit, could make the + // threshold value user definable. + if (pos.x>screenWidth/2.0 && alpha >0.9) { + alpha = 0.9; + } + + // could make the black out colour user definable... + finalColor = vec4( 0, 0, 0, alpha); +} diff --git a/examples/shaders/shaders_spotlight.c b/examples/shaders/shaders_spotlight.c new file mode 100644 index 00000000..ccd91fdc --- /dev/null +++ b/examples/shaders/shaders_spotlight.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019 Chris Camacho (codifies - http://bedroomcoders.co.uk/) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* The shader makes alpha holes in the forground to give the apearance of a top + * down look at a spotlight casting a pool of light... + * + * The right hand side of the screen there is just enough light to see whats + * going on without the spot light, great for a stealth type game where you + * have to avoid the spotlights. + * + * The left hand side of the screen is in pitch dark except for where the spotlights + * are. + * + * Although this example doesn't scale like the letterbox example, you could integrate + * the two techniques, but by scaling the actual colour of the render texture rather + * than using alpha as a mask. + */ + +#include <stddef.h> +#include <stdint.h> + +#include "raylib.h" +#include "raymath.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +// single digit only! +#define MAXSPOT 4 + +#define numStars 400 + +#define screenWidth 1280 +#define screenHeight 720 + +// the stars in the star field have a position and velocity +typedef struct star { + Vector2 pos; + Vector2 vel; +} star; + + +void updateStar(star *s); +void resetStar(star *s); + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + star stars[numStars]; + + for (int n=0; n < numStars; n++) { + resetStar(&stars[n]); + } + + // progress all the stars on, so they don't all start in the centre + for (int m=0; m < screenWidth / 2.0; m++) { + for (int n=0; n<numStars; n++) { + updateStar(&stars[n]); + } + } + + //SetConfigFlags(FLAG_FULLSCREEN_MODE); + InitWindow(screenWidth, screenHeight, "raylib - test"); + + Texture rayTex = LoadTexture("resources/raysan.png"); + + // frame counter + int frame = 0; + + unsigned int spotLoc[MAXSPOT]; // shader locations + + Vector2 spotPos[MAXSPOT]; // position and velocity + Vector2 spotVel[MAXSPOT]; + + // use default vert shader + Shader spotShader = LoadShader(0, FormatText("resources/shaders/glsl%i/spotlight.fs", GLSL_VERSION)); + + // get the locations of spots in the shader + char spotName[32] = "spots[x]\0"; + for (int i = 0; i<MAXSPOT; i++) { + spotName[6] = '0' + i; + spotLoc[i] = GetShaderLocation(spotShader, spotName); + } + + // tell the shader how wide the screen is so we can have + // a pitch black half and a dimly lit half. + { + unsigned int wLoc = GetShaderLocation(spotShader, "screenWidth"); + float sw = screenWidth; + SetShaderValue(spotShader, wLoc, &sw, UNIFORM_FLOAT); + } + + // randomise the locations and velocities of the spotlights + for (int i=0; i<MAXSPOT; i++) { + spotPos[i].x = GetRandomValue(128, screenWidth-128); + spotPos[i].y = GetRandomValue(128, screenHeight-128); + spotVel[i] = (Vector2){0, 0}; + while (fabs(spotVel[i].x)+fabs(spotVel[i].y)<2) { + spotVel[i].x = GetRandomValue(-40,40)/10.0; + spotVel[i].y = GetRandomValue(-40,40)/10.0; + } + } + + + SetTargetFPS(60); // Set to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + frame ++; + + // move the stars, resetting them if the go offscreen + for (int n=0; n<numStars; n++) { + updateStar(&stars[n]); + } + + // update the spots, send them to the shader + for (int i=0; i<MAXSPOT; i++) { + + spotPos[i].x += spotVel[i].x; + spotPos[i].y += spotVel[i].y; + + if (spotPos[i].x < 128) spotVel[i].x = -spotVel[i].x; + if (spotPos[i].x > screenWidth-128) spotVel[i].x = -spotVel[i].x; + if (spotPos[i].y < 128) spotVel[i].y = -spotVel[i].y; + if (spotPos[i].y > screenHeight-128) spotVel[i].y = -spotVel[i].y; + + SetShaderValue(spotShader, spotLoc[i], &spotPos[i].x, UNIFORM_VEC2); + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground((Color){0,32,128,255}); + + // stars and bobs + for (int n=0; n<numStars; n++) { + // single pixel is just too small these days! + DrawRectangle(stars[n].pos.x, stars[n].pos.y, 2, 2, WHITE); + } + + for (int i=0; i<16; i++) { + DrawTexture(rayTex, + (screenWidth/2.0)+cos((frame+i*8)/51.45)*(screenWidth/2.2)-32, + (screenHeight/2.0)+sin((frame+i*8)/17.87)*(screenHeight/4.2), + WHITE); + } + + // spot lights + BeginShaderMode(spotShader); + // instead of a blank rectangle you could render here + // a render texture of the full screen used to do screen + // scaling (slight adjustment to shader would be required + // to actually pay attention to the colour!) + DrawRectangle(0,0,screenWidth,screenHeight,WHITE); + EndShaderMode(); + + DrawFPS(10, 10); + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + UnloadTexture(rayTex); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + + +void resetStar(star *s) +{ + (*s).pos = (Vector2){screenWidth/2.0, screenHeight/2.0 }; + do { + (*s).vel.x = (float)GetRandomValue(-1000,1000) / 100.0; + (*s).vel.y = (float)GetRandomValue(-1000,1000) / 100.0; + } while (!(fabs((*s).vel.x)+fabs((*s).vel.y)>1)); + (*s).pos = Vector2Add( (*s).pos, + Vector2MultiplyV((*s).vel,(Vector2){8,8} )); +} + +void updateStar(star *s) +{ + (*s).pos = Vector2Add((*s).pos, (*s).vel); + if ((*s).pos.x < 0 || (*s).pos.x > screenWidth || + (*s).pos.y < 0 || (*s).pos.y > screenHeight) { + resetStar(s); + } +} + + |
