|
|
@ -1,107 +1,91 @@ |
|
|
|
/* |
|
|
|
* 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> |
|
|
|
/******************************************************************************************* |
|
|
|
* |
|
|
|
* raylib [shaders] example - Simple shader mask |
|
|
|
* |
|
|
|
* This example has been created using raylib 2.5 (www.raylib.com) |
|
|
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) |
|
|
|
* |
|
|
|
* Example contributed by Chris Camacho (@codifies - http://bedroomcoders.co.uk/) |
|
|
|
* and reviewed by Ramon Santamaria (@raysan5) |
|
|
|
* |
|
|
|
* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) |
|
|
|
* |
|
|
|
******************************************************************************************** |
|
|
|
* |
|
|
|
* 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 "raylib.h" |
|
|
|
#include "raymath.h" |
|
|
|
|
|
|
|
#include <stddef.h> |
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
#if defined(PLATFORM_DESKTOP) |
|
|
|
#define GLSL_VERSION 330 |
|
|
|
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB |
|
|
|
#define GLSL_VERSION 100 |
|
|
|
#endif |
|
|
|
|
|
|
|
o">// single digit only! |
|
|
|
#define MAXSPOT 4 |
|
|
|
cp">#define MAXSPOT 2 |
|
|
|
#define numStars 400 |
|
|
|
|
|
|
|
#define numStars 400 |
|
|
|
|
|
|
|
#define screenWidth 1280 |
|
|
|
#define screenHeight 720 |
|
|
|
|
|
|
|
// the stars in the star field have a position and velocity |
|
|
|
typedef struct star { |
|
|
|
// Stars in the star field have a position and velocity |
|
|
|
typedef struct Star { |
|
|
|
Vector2 pos; |
|
|
|
Vector2 vel; |
|
|
|
} star; |
|
|
|
} Star; |
|
|
|
|
|
|
|
|
|
|
|
void updateStar(star *s); |
|
|
|
void resetStar(star *s); |
|
|
|
void UpdateStar(Star *s); |
|
|
|
void ResetStar(Star *s); |
|
|
|
|
|
|
|
int main(void) |
|
|
|
{ |
|
|
|
// Initialization |
|
|
|
//-------------------------------------------------------------------------------------- |
|
|
|
star stars[numStars]; |
|
|
|
const int screenWidth = 800; |
|
|
|
const int screenHeight = 450; |
|
|
|
|
|
|
|
for (int n=0; n < numStars; n++) { |
|
|
|
resetStar(&stars[n]); |
|
|
|
} |
|
|
|
InitWindow(screenWidth, screenHeight, "raylib - shader spotlight"); |
|
|
|
|
|
|
|
// 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]); |
|
|
|
} |
|
|
|
} |
|
|
|
Texture texRay = LoadTexture("resources/raysan.png"); |
|
|
|
|
|
|
|
Star stars[numStars] = { 0 }; |
|
|
|
|
|
|
|
//SetConfigFlags(FLAG_FULLSCREEN_MODE); |
|
|
|
InitWindow(screenWidth, screenHeight, "raylib - test"); |
|
|
|
for (int n = 0; n < numStars; n++) ResetStar(&stars[n]); |
|
|
|
|
|
|
|
Texture rayTex = LoadTexture("resources/raysan.png"); |
|
|
|
// 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]); |
|
|
|
} |
|
|
|
|
|
|
|
// frame counter |
|
|
|
int frame = 0; |
|
|
|
int frameCounter = 0; |
|
|
|
|
|
|
|
unsigned int spotLoc[MAXSPOT]; // shader locations |
|
|
|
unsigned int spotLoc[MAXSPOT]; // shader locations |
|
|
|
|
|
|
|
Vector2 spotPos[MAXSPOT]; // position and velocity |
|
|
|
Vector2 spotPos[MAXSPOT]; // position and velocity |
|
|
|
Vector2 spotVel[MAXSPOT]; |
|
|
|
|
|
|
|
// use default vert shader |
|
|
|
// 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 |
|
|
|
// Get the locations of spots in the shader |
|
|
|
char spotName[32] = "spots[x]\0"; |
|
|
|
for (int i = 0; i<MAXSPOT; i++) { |
|
|
|
for (int i = 0; i < MAXSPOT; i++) |
|
|
|
{ |
|
|
|
spotName[6] = '0' + i; |
|
|
|
spotLoc[i] = GetShaderLocation(spotShader, spotName); |
|
|
|
} |
|
|
@ -110,47 +94,47 @@ int main(void) |
|
|
|
// a pitch black half and a dimly lit half. |
|
|
|
{ |
|
|
|
unsigned int wLoc = GetShaderLocation(spotShader, "screenWidth"); |
|
|
|
float sw = screenWidth; |
|
|
|
float sw = p">(n>floatspan>)GetScreenWidth(); |
|
|
|
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; |
|
|
|
for (int i = 0; i < MAXSPOT; i++) |
|
|
|
{ |
|
|
|
spotPos[i].x = GetRandomValue(64, screenWidth - 64); |
|
|
|
spotPos[i].y = GetRandomValue(64, screenHeight - 64); |
|
|
|
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 |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
frameCounter++; |
|
|
|
|
|
|
|
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++) { |
|
|
|
// 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; |
|
|
|
if (spotPos[i].x < 64) spotVel[i].x = -spotVel[i].x; |
|
|
|
if (spotPos[i].x > screenWidth - 64) spotVel[i].x = -spotVel[i].x; |
|
|
|
if (spotPos[i].y < 64) spotVel[i].y = -spotVel[i].y; |
|
|
|
if (spotPos[i].y > screenHeight - 64) spotVel[i].y = -spotVel[i].y; |
|
|
|
|
|
|
|
SetShaderValue(spotShader, spotLoc[i], &spotPos[i].x, UNIFORM_VEC2); |
|
|
|
} |
|
|
@ -159,22 +143,24 @@ int main(void) |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
BeginDrawing(); |
|
|
|
|
|
|
|
ClearBackground(p">(Color){0,32,128,255}); |
|
|
|
ClearBackground(n">DARKBLUE); |
|
|
|
|
|
|
|
// stars and bobs |
|
|
|
for (int n=0; n<numStars; n++) { |
|
|
|
// single pixel is just too small these days! |
|
|
|
// Draw 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), |
|
|
|
for (int i = 0; i < 16; i++) |
|
|
|
{ |
|
|
|
DrawTexture(texRay, |
|
|
|
(screenWidth/2.0) + cos((frameCounter + i*8)/51.45f)*(screenWidth/2.2) - 32, |
|
|
|
(screenHeight/2.0) + sin((frameCounter + i*8)/17.87f)*(screenHeight/4.2), |
|
|
|
WHITE); |
|
|
|
} |
|
|
|
|
|
|
|
// spot lights |
|
|
|
// Draw spot lights |
|
|
|
BeginShaderMode(spotShader); |
|
|
|
// instead of a blank rectangle you could render here |
|
|
|
// a render texture of the full screen used to do screen |
|
|
@ -185,15 +171,13 @@ int main(void) |
|
|
|
|
|
|
|
DrawFPS(10, 10); |
|
|
|
|
|
|
|
|
|
|
|
EndDrawing(); |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
} |
|
|
|
|
|
|
|
// De-Initialization |
|
|
|
//-------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
UnloadTexture(rayTex); |
|
|
|
UnloadTexture(texRay); |
|
|
|
|
|
|
|
CloseWindow(); // Close window and OpenGL context |
|
|
|
//-------------------------------------------------------------------------------------- |
|
|
@ -202,23 +186,28 @@ int main(void) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void resetStar(star *s) |
|
|
|
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} )); |
|
|
|
s->pos = (Vector2){ GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }; |
|
|
|
|
|
|
|
do |
|
|
|
{ |
|
|
|
s->vel.x = (float)GetRandomValue(-1000, 1000)/100.0f; |
|
|
|
s->vel.y = (float)GetRandomValue(-1000, 1000)/100.0f; |
|
|
|
|
|
|
|
} 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) |
|
|
|
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); |
|
|
|
s->pos = Vector2Add(s->pos, s->vel); |
|
|
|
|
|
|
|
if (s->pos.x < 0 || s->pos.x > GetScreenWidth() || |
|
|
|
s->pos.y < 0 || s->pos.y > GetScreenHeight()) |
|
|
|
{ |
|
|
|
ResetStar(s); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|