summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorchriscamacho <[email protected]>2020-03-24 13:27:14 +0000
committerGitHub <[email protected]>2020-03-24 14:27:14 +0100
commitefe359d61303b2148199c009abab34e44b0ab04f (patch)
tree9d0b1e0ed67617f65cc5ce99db178c9232bfe5f4
parentc45fe62abcf7d710678f7f4bc25dc9b1bfdc8ea2 (diff)
downloadraylib-efe359d61303b2148199c009abab34e44b0ab04f.tar.gz
raylib-efe359d61303b2148199c009abab34e44b0ab04f.zip
as per request spotlight example (#1146)
Co-authored-by: codifies <[email protected]>
-rw-r--r--examples/Makefile3
-rw-r--r--examples/shaders/resources/raysan.pngbin0 -> 15064 bytes
-rw-r--r--examples/shaders/resources/shaders/glsl100/spotlight.fs52
-rw-r--r--examples/shaders/resources/shaders/glsl330/spotlight.fs53
-rw-r--r--examples/shaders/shaders_spotlight.c225
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
new file mode 100644
index 00000000..3d4e70fe
--- /dev/null
+++ b/examples/shaders/resources/raysan.png
Binary files differ
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);
+ }
+}
+
+